<!DOCTYPE html>
<html lang="ko" dir="ltr">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>zustand – codthing</title>
    


  
  <script defer src="/js/fuse.min.c4bee9a8d44273d6154fe86006923d4131eb2e8069d8897687137c6f37f553e3.js"></script>



<script src="/js/enquire.min.aa37bdcb743826eecdae5c5d177fc7d6552340f1b4378ffaa9c82b2c6111400b.js"></script>

<script defer src="/js/lazysizes.min.5e11d056075a05065b9c0bfec44084a113fc2976c2952ec804dedb61c7662db9.js"></script>

<script defer src="/js/helper/getParents.min.cd44056d552c69703dced61ae60f99166a0ddf44be93d6aa5d5127d98bf98984.js"></script>

<script defer src="/js/helper/fadeinout.min.58d290b487a552ce9c144bf938c2758c4a3afbc4f17d70d11771c9e3c61fe3d0.js"></script>

<script>
  "use strict";

  window.onload = function() {
    
    var languagedir = JSON.parse("\"ltr\"");
    
    var baseurl = JSON.parse("\"https://codthing.github.io/\"");
    
    var permalink = JSON.parse("\"https://codthing.github.io/react/zustand/zustand-base/\"");

    
    var toggleSidebarElem = document.getElementById("toggle-sidebar");
    var toggleMenuElem = document.getElementById("toggle-menu");
    var tocBodyElem = document.querySelector('.toc__body');
    var tocLabelElem = document.querySelector('.toc__label');
    var listMainElem = document.getElementById('list-main');
    var listSideElem = document.getElementById('list-side');
    var singleMenuElem = document.getElementById('single-menu');
    var sliderIcons = document.querySelectorAll('.slider__icon');

    toggleSidebarElem ?
      toggleSidebarElem.addEventListener('change', function (e) {
        if (e.target.checked) {
          if (tocBodyElem) {
            fadeIn(tocBodyElem, 200);
          }
          if (tocLabelElem) {
            fadeIn(tocLabelElem, 200);
          }
          if (listMainElem && listSideElem) {
            listMainElem.className = 'm';
            listSideElem.className = 'r';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });

        } else {
          if (tocBodyElem) {
            fadeOut(tocBodyElem, 200);
          }
          if (tocLabelElem) {
            fadeOut(tocLabelElem, 200);
          }
          if (listMainElem && listSideElem) {
            listMainElem.className = 'mr';
            listSideElem.className = 'hide';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });
        }
      }) : null;

    toggleMenuElem ?
      toggleMenuElem.addEventListener('change', function (e) {
        if (e.target.checked) {
          if (listMainElem && singleMenuElem) {
            listMainElem.className = 'm';
            singleMenuElem.className = 'l';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });

        } else {
          if (listMainElem && singleMenuElem) {
            listMainElem.className = 'lm';
            singleMenuElem.className = 'hide';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });
        }
      }) : null;
    


    
    var navCollapseBtn = document.getElementById('navCollapseBtn');
    navCollapseBtn ? navCollapseBtn.addEventListener('click', function(e) {
      var navCollapse = document.querySelector('.navbar__collapse');
      
      if (navCollapse) {
        var dataOpen = navCollapse.getAttribute('data-open');

        if (dataOpen === 'true') {
          navCollapse.setAttribute('data-open', 'false');
          navCollapse.style.maxHeight = 0;
        } else {
          navCollapse.setAttribute('data-open', 'true');
          navCollapse.style.maxHeight = navCollapse.scrollHeight + "px";
        }
      }
    }) : null;
    


    
    var expandBtn = document.querySelectorAll('.expand__button');

    for (let i = 0; i < expandBtn.length; i++) {
      expandBtn[i].addEventListener("click", function () {
        var content = this.nextElementSibling;
        if (content.style.maxHeight) {
          content.style.maxHeight = null;
          this.querySelector('svg').classList.add('expand-icon__right');
          this.querySelector('svg').classList.remove('expand-icon__down');
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
          this.querySelector('svg').classList.remove('expand-icon__right');
          this.querySelector('svg').classList.add('expand-icon__down');
        }
      });
    }
    



    
    document.querySelectorAll('.tab') ? 
    document.querySelectorAll('.tab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var tabLinks = elem.querySelectorAll('.tab__link');
      var tabContents = elem.querySelectorAll('.tab__content');
      var ids = [];

      tabLinks && tabLinks.length > 0 ?
      tabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                tabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              tabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    


    
    document.querySelectorAll('.codetab') ? 
    document.querySelectorAll('.codetab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var codetabLinks = elem.querySelectorAll('.codetab__link');
      var codetabContents = elem.querySelectorAll('.codetab__content');
      var ids = [];

      codetabLinks && codetabLinks.length > 0 ?
      codetabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                codetabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              codetabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    

    
    
    
    var enableDarkMode = JSON.parse("true");
    var root = document.getElementById('root');
    var toggleToLightBtn = document.getElementById('toggleToLight');
    var toggleToDarkBtn = document.getElementById('toggleToDark');

    if (!enableDarkMode) {
      root.className = 'theme__light';
      localStorage.setItem('theme', 'light');
    }
    
    if (toggleToDarkBtn) {
      toggleToDarkBtn.onclick = function (e) {
        root.className = 'theme__dark';
        localStorage.setItem('theme', 'dark');
        toggleToLightBtn.className = 'navbar__icons--icon';
        toggleToDarkBtn.className = 'hide';
      }
    }

    if (toggleToLightBtn) {
      toggleToLightBtn.onclick = function (e) {
        root.className = 'theme__light';
        localStorage.setItem('theme', 'light');
        toggleToLightBtn.className = 'hide';
        toggleToDarkBtn.className = 'navbar__icons--icon';
      }
    }

    
    document.querySelectorAll('.menu__list').forEach(function(elem) {
      if (elem.classList.contains('active')) {
        elem.style.maxHeight = elem.scrollHeight + "px"; 
      }
    });
    
    document.querySelectorAll('.menu__title--collapse').forEach(function(elem) {
      elem.addEventListener('click', function (e) {
        var content = this.nextElementSibling;
        var menuTitleIcon = this.querySelector('.menu__title--icon');
        if (!content) {
          return null;
        }

        var parent = elem.parentNode;
        while (parent.classList.contains('menu__list') && parent.classList.contains('active')) {
          parent.style.maxHeight = 100 * parent.children.length + "px";
          parent = parent.parentNode;
        }

        if (content.style.maxHeight) {
          content.style.maxHeight = null;
          content.classList.remove('active');
          menuTitleIcon.classList.add('right');
          
          if (languagedir === 'rtl') {
            menuTitleIcon.classList.remove('downrtl');
          } else {
            menuTitleIcon.classList.remove('down');
          }
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
          content.classList.add('active');
          menuTitleIcon.classList.remove('right');
          
          if (languagedir === 'rtl') {
            menuTitleIcon.classList.add('downrtl');
          } else {
            menuTitleIcon.classList.add('down');
          }
        }
      });
    });
    


    
    var mobileLogo = document.getElementById('mobileLogo');
    var modal = document.getElementById("myModal");
    var drawer = document.getElementById('myDrawer');
    var drawerCloseBtn = document.querySelector('.drawer__close');

    var openDrawer = function() {
      modal.style.opacity = 1;

      if (languagedir === 'rtl') {
        modal.style.right = 0;
        drawer.style.right = 0;
      } else {
        modal.style.left = 0;
        drawer.style.left = 0;
      }
    }

    var closeDrawer = function() {
      modal.style.opacity = 0;

      if (languagedir === 'rtl') {
        drawer.style.right = '-100%';
      } else {
        drawer.style.left = '-100%';
      }

      
      setTimeout(function () {
        if (languagedir === 'rtl') {
          modal.style.right = '-100%';
        } else {
          modal.style.left = '-100%';
        }
      }, 250);
    }

    mobileLogo.onclick = function () {
      openDrawer();
      localStorage.setItem('isDrawerOpen', 'true');
    }

    modal.onclick = function () {
      closeDrawer();
      localStorage.setItem('isDrawerOpen', 'false');
    }

    drawerCloseBtn.onclick = function () {
      closeDrawer();
      localStorage.setItem('isDrawerOpen', 'false');
    }
  


  
    var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
    var tocElem = document.querySelector('.toc');
    var tableOfContentsElem = tocElem ? tocElem.querySelector('#TableOfContents') : null;
    var singleContentsElem = document.querySelector('.single__contents');
    var dataBGImgs = document.querySelectorAll('div[data-bgimg]');

    
    var tocLevels = JSON.parse("[\"h2\",\"h3\",\"h4\"]");

    if (tocLevels) {
      tocLevels = tocLevels.toString();
    } else {
      tocLevels = "h1, h2, h3, h4, h5, h6";
    }

    
    var isLandingBgImg = JSON.parse("null");
    
    var isHome = JSON.parse("false");

    function setNavbarBG(scrollTop) {
      if (isHome && isLandingBgImg && Object.keys(isLandingBgImg).length) {
        if (isLandingBgImg.height <= scrollTop) {
          dataBGImgs.forEach(function(elem) {
            elem.setAttribute('data-bgimg', 'false');
          });
        } else {
          dataBGImgs.forEach(function (elem) {
            elem.setAttribute('data-bgimg', 'true');
          });
        }
      }
    }
    setNavbarBG(lastScrollTop);

    window.onscroll = function () {
      var st = window.pageYOffset || document.documentElement.scrollTop;
      if (st > lastScrollTop) { 
        singleContentsElem ? 
        singleContentsElem.querySelectorAll(tocLevels.toString()).forEach(function(elem) {
          if (document.documentElement.scrollTop >= elem.offsetTop) {
            if (tableOfContentsElem) {
              var id = elem.getAttribute('id');
              tocElem.querySelectorAll('a').forEach(function (elem) {
                elem.classList.remove('active');
              });
              tocElem.querySelector('a[href="#' + id + '"]') ? 
              tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;
            }
          }
        }) : null;
        setNavbarBG(st);
      } else { 
        singleContentsElem ? 
        singleContentsElem.querySelectorAll(tocLevels.toString()).forEach(function(elem) {
          if (document.documentElement.scrollTop >= elem.offsetTop) {
            if (tableOfContentsElem) {
              var id = elem.getAttribute('id');
              tocElem.querySelectorAll('a').forEach(function (elem) {
                elem.classList.remove('active');
              });
              tocElem.querySelector('a[href="#' + id + '"]') ? 
              tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;
            }
          }
        }) : null;
        setNavbarBG(st);
      }
      lastScrollTop = st <= 0 ? 0 : st;
    };
    



    
    var mobileSearchInputElem = document.querySelector('#search-mobile');
    var mobileSearchClassElem = document.querySelector('.mobile-search');
    var mobileSearchBtnElem = document.querySelector('#mobileSearchBtn');
    var mobileSearchCloseBtnElem = document.querySelector('#search-mobile-close');
    var mobileSearchContainer = document.querySelector('#search-mobile-container');
    var mobileSearchResultsElem = document.querySelector('#search-mobile-results');
    var htmlElem = document.querySelector('html');

    if (mobileSearchClassElem) {
      mobileSearchClassElem.style.display = 'none';
    }

    mobileSearchBtnElem ? 
    mobileSearchBtnElem.addEventListener('click', function () {
      if (mobileSearchContainer) {
        mobileSearchContainer.style.display = 'block';
      }

      if (mobileSearchInputElem) {
        mobileSearchInputElem.focus();
      }

      if (htmlElem) {
        htmlElem.style.overflowY = 'hidden';
      }
    }) : null;

    mobileSearchCloseBtnElem ? 
    mobileSearchCloseBtnElem.addEventListener('click', function() {
      if (mobileSearchContainer) {
        mobileSearchContainer.style.display = 'none';
      }

      if (mobileSearchInputElem) {
        mobileSearchInputElem.value = '';
      }
      
      if (mobileSearchResultsElem) {
        while (mobileSearchResultsElem.firstChild) {
          mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
        }
      }

      if (htmlElem) {
        htmlElem.style.overflowY = 'visible';
      }
    }) : null;

    mobileSearchInputElem ? 
    mobileSearchInputElem.addEventListener('keydown', function(e) {
      if (e.key === 'Escape') {
        if (mobileSearchContainer) {
          mobileSearchContainer.style.display = 'none';
        }
        
        if (mobileSearchInputElem) {
          mobileSearchInputElem.value = '';
        }

        if (mobileSearchResultsElem) {
          while (mobileSearchResultsElem.firstChild) {
            mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
          }
        }
        if (htmlElem) {
          htmlElem.style.overflowY = 'visible';
        }
      }
    }) : null;
  


  
    var localTheme = localStorage.getItem('theme');
    var rootEleme = document.getElementById('root');
    var selectThemeElem = document.querySelectorAll('.select-theme');
    var selectThemeItemElem = document.querySelectorAll('.select-theme__item');
    
    if (localTheme) {
      selectThemeItemElem ? 
      selectThemeItemElem.forEach(function (elem) {
        if (elem.text.trim() === localTheme) {
          elem.classList.add('is-active');
        } else {
          elem.classList.remove('is-active');
        }
      }) : null;
    }

    selectThemeItemElem ? 
    selectThemeItemElem.forEach(function (v, i) {
      v.addEventListener('click', function (e) {
        var selectedThemeVariant = e.target.text.trim();
        localStorage.setItem('theme', selectedThemeVariant);

        rootEleme.removeAttribute('class');
        rootEleme.classList.add(`theme__${selectedThemeVariant}`);
        selectThemeElem.forEach(function(rootElem) {
          rootElem.querySelectorAll('a').forEach(function (elem) {
            if (elem.classList) {
              if (elem.text.trim() === selectedThemeVariant) {
                if (!elem.classList.contains('is-active')) {
                  elem.classList.add('is-active');
                }
              } else {
                if (elem.classList.contains('is-active')) {
                  elem.classList.remove('is-active');
                }
              }
            }
          });
        });

        if (window.mermaid) {
          if (selectedThemeVariant === "dark" || selectedThemeVariant === "hacker") {
            mermaid.initialize({ theme: 'dark' });
            location.reload();
          } else {
            mermaid.initialize({ theme: 'default' });
            location.reload();
          }
        }

        var utterances = document.querySelector('iframe');
        if (utterances) {
          utterances.contentWindow.postMessage({
            type: 'set-theme',
            theme: selectedThemeVariant === "dark" || selectedThemeVariant === "hacker" ? 'photon-dark' : selectedThemeVariant === 'kimbie' ? 'github-dark-orange' : 'github-light',
          }, 'https://utteranc.es');
        }
      });
    }) : null;
  


  
    
    var langprefix = JSON.parse("\"\"");
    var searchResults = null;
    var searchMenu = null;
    var searchText = null;
    
    
    var enableSearchHighlight = JSON.parse("true");
    
    var enableSearch = JSON.parse("true");

    var fuse = null;

    if (enableSearch) {
      (function initFuse() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', baseurl + langprefix + "/index.json");
        xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
        xhr.onload = function () {
          if (xhr.status === 200) {
            fuse = new Fuse(JSON.parse(xhr.response.toString('utf-8')), {
              keys: ['title', 'description', 'content'],
              includeMatches: enableSearchHighlight,
              shouldSort: true,
              threshold: 0.4,
              location: 0,
              distance: 100,
              maxPatternLength: 32,
              minMatchCharLength: 1,
            });
          }
          else {
            console.error(`[${xhr.status}]Error:`, xhr.statusText);
          }
        };
        xhr.send();
      })();
    }
    
    function makeLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      
      var a = document.createElement('a');
      a.innerHTML = obj.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.permalink);

      var descDiv = document.createElement('div');
      descDiv.setAttribute('class', 'search-result__item--desc');
      if (obj.description) {
        descDiv.innerHTML = obj.description;
      } else if (obj.content) {
        descDiv.innerHTML = obj.content.substring(0, 80);
      }
      
      li.appendChild(a);
      li.appendChild(descDiv);
      ulElem.appendChild(li);
    }

    function makeHighlightLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      var descDiv = null;

      var a = document.createElement('a');
      a.innerHTML = obj.item.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.item.uri);

      if (obj.matches && obj.matches.length) {
        for (var i = 0; i < obj.matches.length; i++) {
          if ('title' === obj.matches[i].key) {
            a = document.createElement('a');
            a.innerHTML = generateHighlightedText(obj.matches[i].value, obj.matches[i].indices);
            a.setAttribute('class', 'search-result__item--title');
            a.setAttribute('href', obj.item.uri);
          }
          
          if ('description' === obj.matches[i].key) {
            descDiv = document.createElement('div');
            descDiv.setAttribute('class', 'search-result__item--desc');
            descDiv.innerHTML = generateHighlightedText(obj.item.description, obj.matches[i].indices);
          } else if ('content' === obj.matches[i].key) {
            if (!descDiv) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = generateHighlightedText(obj.item.content.substring(0, 80), obj.matches[i].indices);
            }
          } else {
            if (obj.item.description) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.description;
            } else {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.content.substring(0, 80);
            }
          }
        }

        li.appendChild(a);
        if (descDiv) {
          li.appendChild(descDiv);
        }
        if (li) {
          ulElem.appendChild(li);
        }
      }
    }

    function renderSearchResults(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dd is-active');
      
      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dd-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          a.setAttribute('href', result.uri);
          a.setAttribute('class', 'dd-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.title;
          titleDiv.setAttribute('class', 'search-result__item--title');

          var descDiv = document.createElement('div');
          descDiv.setAttribute('class', 'search-result__item--desc');
          if (result.description) {
            descDiv.innerHTML = result.description;
          } else if (result.content) {
            descDiv.innerHTML = result.content.substring(0, 80);
          }

          li.appendChild(titleDiv);
          li.appendChild(descDiv);
          ul.appendChild(a);
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dd-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      
      searchMenu.appendChild(ul);
    }

    function renderSearchHighlightResults(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dd is-active');

      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dd-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.setAttribute('class', 'dd-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'search-result__item--title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'search-result__item--desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'search-result__item--desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 80), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'search-result__item--desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'search-result__item--desc');
                  descDiv.innerHTML = result.item.content.substring(0, 80);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dd-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      searchMenu.appendChild(ul);
    }

    function renderSearchResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var content = document.createElement('div');
      content.setAttribute('class', 'mobile-search__content');

      if (results.length > 0) {
        results.forEach(function (result) {
          var item = document.createElement('a');
          item.setAttribute('href', result.uri);
          item.innerHTML = '<div class="mobile-search__item"><div class="mobile-search__item--title">📄 ' + result.title + '</div><div class="mobile-search__item--desc">' + (result.description ? result.description : result.content) + '</div></div>';
          content.appendChild(item);
        });
      } else {
        var item = document.createElement('span');
        content.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(content);      
    }

    function renderSearchHighlightResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var ul = document.createElement('div');
      ul.setAttribute('class', 'mobile-search__content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.appendChild(li);
          li.setAttribute('class', 'mobile-search__item');

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'mobile-search__item--title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'mobile-search__item--desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 150), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.content.substring(0, 150);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var item = document.createElement('span');
        ul.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(ul);
    }

    function generateHighlightedText(text, regions) {
      if (!regions) {
        return text;
      }

      var content = '', nextUnhighlightedRegionStartingIndex = 0;

      regions.forEach(function(region) {
        if (region[0] === region[1]) {
          return null;
        }
        
        content += '' +
          text.substring(nextUnhighlightedRegionStartingIndex, region[0]) +
          '<span class="search__highlight">' +
            text.substring(region[0], region[1] + 1) +
          '</span>' +
        '';
        nextUnhighlightedRegionStartingIndex = region[1] + 1;
      });

      content += text.substring(nextUnhighlightedRegionStartingIndex);

      return content;
    };

    var searchElem = document.getElementById('search');
    var searchMobile = document.getElementById('search-mobile');
    var searchResultsContainer = document.getElementById('search-results');

    searchElem ? 
    searchElem.addEventListener('input', function(e) {
      if (!e.target.value | window.innerWidth < 770) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dd') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);

      if (enableSearchHighlight) {
        renderSearchHighlightResults(searchText, results);
      } else {
        renderSearchResults(searchText, results);
      }

      var dropdownItems = searchResultsContainer.querySelectorAll('.dd-item');
      dropdownItems ? dropdownItems.forEach(function (item) {
        item.addEventListener('mousedown', function (e) {
          e.target.click();
        });
      }) : null;
    }) : null;

    searchElem ? 
    searchElem.addEventListener('blur', function() {
      if (window.innerWidth < 770) {
        return null;
      }
      searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dd') : null;
    }) : null;

    searchElem ? 
    searchElem.addEventListener('click', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }
      if (!e.target.value) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dd') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);

      if (enableSearchHighlight) {
        renderSearchHighlightResults(searchText, results);
      } else {
        renderSearchResults(searchText, results);
      }

      var dropdownItems = searchResultsContainer.querySelectorAll('.dd-item');
      dropdownItems ? dropdownItems.forEach(function (item) {
        item.addEventListener('mousedown', function (e) {
          e.target.click();
        });
      }) : null;
    }) : null;

    var searchMenuElem = document.getElementById("search-menu");
    var activeItem = document.querySelector('#search-menu .dd-item.is-active');
    var activeIndex = null;
    var items = null;
    var searchContainerMaxHeight = 350;

    searchElem ? 
    searchElem.addEventListener('keydown', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }

      var items = document.querySelectorAll('#search-menu .dd-item');
      
      if (e.key === 'ArrowDown') {
        if (activeIndex === null) {
          activeIndex = 0;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === items.length - 1 ? 0 : activeIndex + 1;
        }
        items[activeIndex].classList.add('is-active');

        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel > 0) {
          document.querySelector(".search-content").scrollTop += items[activeIndex].getBoundingClientRect().height;
        } else if (activeIndex === 0) {
          document.querySelector(".search-content").scrollTop = 0;
        }
      } else if (e.key === 'ArrowUp') {
        if (activeIndex === null) {
          activeIndex = items.length - 1;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1;
        }
        items[activeIndex].classList.add('is-active');
        
        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel < 0) {
          document.querySelector(".search-content").scrollTop -= items[activeIndex].getBoundingClientRect().height;
        } else {
          document.querySelector(".search-content").scrollTop = overflowedPixel + items[activeIndex].getBoundingClientRect().height;
        }
      } else if (e.key === 'Enter') {
        var currentItemLink = items[activeIndex].getAttribute('href');
        if (currentItemLink) {
          location.href = currentItemLink;
        }
      } else if (e.key === 'Escape') {
        e.target.value = null;
        if (searchResults) {
          searchResults.classList.remove('is-active');
        }
      }
    }) : null;

    searchMobile ? 
    searchMobile.addEventListener('input', function(e) {
      if (!e.target.value) {
        let wrap = document.getElementById('search-mobile-results');
        while (wrap.firstChild) {
          wrap.removeChild(wrap.firstChild);
        }
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);
      
      if (enableSearchHighlight) {
        renderSearchHighlightResultsMobile(searchText, results);
      } else {
        renderSearchResultsMobile(searchText, results);
      }

      var dropdownItems = searchResultsContainer.querySelectorAll('.dd-item');
      dropdownItems ? dropdownItems.forEach(function (item) {
        item.addEventListener('mousedown', function (e) {
          e.target.click();
        });
      }) : null;
    }) : null;
  
  }
</script>
    


<link rel="stylesheet" href="/css/main.min.css">


    <meta name="description" content="使用简化的通量原理的小型、快速且可扩展的React状态管理解决方案。有一个基于钩子的舒适 api。这是我感觉最好的React的状态管理库，很可爱。" />
<meta name="keywords" content="">
<meta name="created" content="2020-01-28T00:34:39&#43;0900">
<meta name="modified" content="2020-01-28T00:34:39&#43;0900">


<meta property="og:site_name" content="codthing">
<meta property="og:title" content="zustand">
<meta property="og:url" content="https://codthing.github.io/react/zustand/zustand-base/">
<meta property="og:type" content="article">

<meta name="generator" content="Hugo 0.95.0" />
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="theme-color" content="#ffffff">
<link rel="canonical" href="https://codthing.github.io/react/zustand/zustand-base/">
<link rel="manifest" href="/manifest.json">

  <link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
  <link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
  <link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png">
  <link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
  <link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
  <link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
  <link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
  <link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
  <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
  <link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png">
  <link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-512x512.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
  <meta name="msapplication-TileColor" content="#ffffff">
  <meta name="msapplication-TileImage" content="/ms-icon-144x144.png">

    <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "WebPage",
    "headline": "zustand",
    "datePublished": "2020-01-28T00:34:39+09:00",
    "dateModified": "2020-01-28T00:34:39+09:00",
    "url" : "https://codthing.github.io/react/zustand/zustand-base/",
    "description": "使用简化的通量原理的小型、快速且可扩展的React状态管理解决方案。有一个基于钩子的舒适 api。这是我感觉最好的React的状态管理库，很可爱。",
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://codthing.github.io/"
    },
    "publisher": {
      "@type": "Organization",
      "name": "codthing",
      "url": "https://codthing.github.io/"
    }
  }
</script>

    

</head>


<body id="root" class="theme__dark">
    <script>
        var rootElem = document.getElementById('root');
        var themeOptions = JSON.parse("[\"dark\",\"light\"]");
        var localTheme = localStorage.getItem('theme');

        if (localTheme) {
            if (themeOptions && themeOptions.length > 0) {
                themeOptions.includes(localTheme) ? 
                rootElem.className = `theme__${localTheme}` :
                rootElem.className = `theme__${themeOptions[0]}`;
            }
        }
    </script>
    
    <div id="container">
        <div id="myDrawer" class="drawer" style="">
  <div class="drawer__header">
    <a href="/" class="drawer__header--text">
      
    </a>
    <div class="grow"></div>
    <div class="drawer__close">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z"/></svg>
    </div>
  </div>

  <div class="drawer__body">
    <div class="menu">
  <h6 class="menu__label">
    
      zustand
    
  </h6>
  <ul>
    
    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/redux/react-redux/"
      class="menu__title ">React &amp; Redux</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/react/react-base/"
      class="menu__title ">React 基础</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/react/react-bp/"
      class="menu__title ">React 最佳实践</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/redux/redux-base/"
      class="menu__title ">Redux</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/hooks/hooks-bp/"
      class="menu__title ">Hooks 最佳实践</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/redux/hooks-redux/"
      class="menu__title ">Hooks &amp; Redux</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="active">
    <a href="https://codthing.github.io/react/zustand/zustand-base/"
      class="menu__title active">zustand</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/recoil/recoil-bp/"
      class="menu__title ">Recoil 最佳实践</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/next/">
    <span class="menu__title--collapse-text">
      Next.js
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/next/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/next/next-base/" class="menu__title " data-depth="0">Next.js 速览</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/next/next-content/" class="menu__title " data-depth="0">Next.js 核心工作内容</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/next/next-multiple/" class="menu__title " data-depth="0">Next.js 各种组合</a>
        </li>
      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/remix/remix-base/"
      class="menu__title ">Remix 基础</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/remix/remix-adv/"
      class="menu__title ">Remix 进阶</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/storybook/">
    <span class="menu__title--collapse-text">
      Storybook
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/storybook/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-bp/" class="menu__title " data-depth="0">Storybook 最佳实践</a>
        </li>
      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/storybook/sb-started/">
    <span class="menu__title--collapse-text">
      开始
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/sb-started/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-introduction/" class="menu__title " data-depth="1">介绍</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-install/" class="menu__title " data-depth="1">安装</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-what/" class="menu__title " data-depth="1">Story 是什么？</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-browse/" class="menu__title " data-depth="1">浏览故事</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-setup/" class="menu__title " data-depth="1">设置</a>
        </li>
      
    
  </ul>
  

      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/storybook/sb-write/">
    <span class="menu__title--collapse-text">
      写故事
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/sb-write/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
  </ul>
  

      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/storybook/sb-test/">
    <span class="menu__title--collapse-text">
      编写测试
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/sb-test/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-test/sb-test-introduction/" class="menu__title " data-depth="1">介绍</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-test/sb-visual-tests/" class="menu__title " data-depth="1">视觉测试</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-test/sb-accessibility-testing/" class="menu__title " data-depth="1">可访问性测试</a>
        </li>
      
    
  </ul>
  

      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/tailwindcss/">
    <span class="menu__title--collapse-text">
      tailwindcss
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/tailwindcss/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/tailwindcss/tailwindcss-start.md/">
    <span class="menu__title--collapse-text">
      开始
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/tailwindcss-start.md/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/tailwindcss/tailwindcss-start.md/tailwindcss-install/" class="menu__title " data-depth="1">安装</a>
        </li>
      
    
  </ul>
  

      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/wechat-mini/">
    <span class="menu__title--collapse-text">
      小程序开发
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/wechat-mini/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/wechat-mini/taro-log/" class="menu__title " data-depth="0">Taro开发日志</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/wechat-mini/remax-log/" class="menu__title " data-depth="0">Remax开发日志</a>
        </li>
      
    
  </ul>
  

    
  </ul>
</div>



<script>
  var menuTitle = document.querySelectorAll('.menu__title');
  var modal = document.getElementById("myModal");
  var drawer = document.getElementById('myDrawer');

  var closeDrawer = function () {
    setTimeout(function () {
      modal.style.opacity = 0;
      drawer.style.left = '-100%';
      modal.style.left = '-100%';
    }, 250);
  }

  menuTitle ? 
  menuTitle.forEach(function(elem) {
    elem.onclick = function() {
      closeDrawer();
      localStorage.setItem('isDrawerOpen', 'false');
    }
  }) : null;
</script>
  </div>
</div>
<div id="myModal" class="modal" style=""></div>

<script>
  var isDrawerOpen = localStorage.getItem('isDrawerOpen');
  var modal = document.getElementById("myModal");
  var drawer = document.getElementById('myDrawer');
  
  
  var languagedir = JSON.parse("\"ltr\"");

  var openDrawer = function () {
    modal.style.opacity = 1;
    
    if (languagedir === "rtl") {
      modal.style.right = 0;
      drawer.style.right = 0;
    } else {
      modal.style.left = 0;
      drawer.style.left = 0;
    }
  }

  if (isDrawerOpen && isDrawerOpen === 'true') {
    openDrawer();
  }
</script>
        
<nav class="nav">
  <div class="navbar__wrapper" data-bgimg="false">
    <div class="divider">
      <div class="navbar lmr">
        <div id="siteLogo" class="navbar__logo--wrapper">
  
    &nbsp;&nbsp;
  
  
    <a href="/" title="" rel="home" class="navbar__logo--text-link">
      <h6 class="navbar__logo--text" data-bgimg="false"></h6>
    </a>
  
</div>
        
        <div class="navbar__menu--wrapper">
          <div id="tabletLogo" class="hide">
  
    <a href="/" rel="home" class="navbar__logo--link">
      <div class="navbar__icons--icon">
        <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z"/></svg>
      </div>
    </a>
  
</div>
          <div id="mobileLogo" class="hide">
  <a href="#" class="navbar__logo--link">
    <div class="navbar__icons--icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M4 18h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1s.45 1 1 1zm0-5h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1s.45 1 1 1zM3 7c0 .55.45 1 1 1h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1z"/></svg>
    </div>
  </a>
</div>
          <span id="navMenuMobile" class="hide">
  <button id="navCollapseBtn" class="navbar__dropdown--title" aria-label="Section Menu" data-dir="ltr">
    
      react
    
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"/></svg>
  </button>
  <div class="navbar__collapse" data-open="false">
  <ul>
    

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/javascript" class="">JavaScript</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/nodejs" class="">Nodejs</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item active">
    <a href="/react" class="active">React</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/react-patterns" class="">React-Patterns</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/react-native" class="">React-Native</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/rust" class="">Rust</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/others" class="">Others</a>
  </li>

  </ul>
</div>
</span>
          <ul id="navMenu" class="navbar__menu">
            

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/javascript" data-bgimg="false">JavaScript</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/nodejs" data-bgimg="false">Nodejs</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item active">
    <a href="/react" data-bgimg="false">React</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/react-patterns" data-bgimg="false">React-Patterns</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/react-native" data-bgimg="false">React-Native</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/rust" data-bgimg="false">Rust</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/others" data-bgimg="false">Others</a>
  </li>

          </ul>
        </div>
        <div class="grow"></div>
        <div id="siteSearch">
          

<div class="search" data-bgimg="false">
  <span class="icon">
    <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
  </span>
  <input id="search" aria-label="Site Search" class="input" type="text" autocomplete="off" placeholder="Search">
  <div id="search-results" class="dropdown">
    <div id="search-menu" class="dropdown-menu">
    </div>
  </div>
</div>


        </div>
        <div id="mobileSearch" class="hide">
          
<div id="mobileSearchBtn" class="mobile-search__btn">
  <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
</div>

<div id="search-mobile-container" class="mobile-search hide">
  <div class="mobile-search__top">
    <input id="search-mobile" type="text" aria-label="Mobile Search" placeholder="Search..." class="mobile-search__top--input"/>
    <div id="search-mobile-close" class="mobile-search__top--icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path opacity=".87" fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41z"/></svg>
    </div>
  </div>
  <div id="search-mobile-results" class="mobile-search__body">
    
  </div>
</div>

        </div>
        <div class="navbar__icons">
  
  
<button id="toggleToDark" class="navbar__icons--icon" aria-label="Toggle to dark mode">
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none" /><path fill="currentColor" d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6z"/></svg>
</button>
<button id="toggleToLight" class="navbar__icons--icon" aria-label="Toggle to light mode">
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path fill="currentColor" d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-10c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"/></svg>
</button>
<script>
  var theme = localStorage.getItem('theme');
  var toggleToLightBtn = document.getElementById('toggleToLight');
  var toggleToDarkBtn = document.getElementById('toggleToDark');

  if (theme && theme === 'dark') {
    toggleToLightBtn.className = 'navbar__icons--icon';
    toggleToDarkBtn.className = 'hide';
  } else {
    toggleToLightBtn.className = 'hide';
    toggleToDarkBtn.className = 'navbar__icons--icon';
  }
</script>

  <div class="navbar__icons--icon">
    <a href="https://github.com/codthing" title="Github repository" aria-label="Github repository" target="_blank" rel="noreferrer">
    <svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="22" height="22"><path d="M10.9,2.1c-4.6,0.5-8.3,4.2-8.8,8.7c-0.5,4.7,2.2,8.9,6.3,10.5C8.7,21.4,9,21.2,9,20.8v-1.6c0,0-0.4,0.1-0.9,0.1 c-1.4,0-2-1.2-2.1-1.9c-0.1-0.4-0.3-0.7-0.6-1C5.1,16.3,5,16.3,5,16.2C5,16,5.3,16,5.4,16c0.6,0,1.1,0.7,1.3,1c0.5,0.8,1.1,1,1.4,1 c0.4,0,0.7-0.1,0.9-0.2c0.1-0.7,0.4-1.4,1-1.8c-2.3-0.5-4-1.8-4-4c0-1.1,0.5-2.2,1.2-3C7.1,8.8,7,8.3,7,7.6c0-0.4,0-0.9,0.2-1.3 C7.2,6.1,7.4,6,7.5,6c0,0,0.1,0,0.1,0C8.1,6.1,9.1,6.4,10,7.3C10.6,7.1,11.3,7,12,7s1.4,0.1,2,0.3c0.9-0.9,2-1.2,2.5-1.3 c0,0,0.1,0,0.1,0c0.2,0,0.3,0.1,0.4,0.3C17,6.7,17,7.2,17,7.6c0,0.8-0.1,1.2-0.2,1.4c0.7,0.8,1.2,1.8,1.2,3c0,2.2-1.7,3.5-4,4 c0.6,0.5,1,1.4,1,2.3v2.6c0,0.3,0.3,0.6,0.7,0.5c3.7-1.5,6.3-5.1,6.3-9.3C22,6.1,16.9,1.4,10.9,2.1z"/></svg>
    </a>
  </div>
</div>


      </div>
    </div>
  </div>
</nav>

<script>
  var siteLogo = document.getElementById('siteLogo');
  var tabletLogo = document.getElementById('tabletLogo');
  var mobileLogo = document.getElementById('mobileLogo');
  var navMenu = document.getElementById('navMenu');
  var navMenuMobile = document.getElementById('navMenuMobile');
  var siteSearch = document.getElementById('siteSearch');
  var mobileSearch = document.getElementById('mobileSearch');
  
  enquire.register("screen and (max-width:1280px)", {
    match: function () {
      siteLogo.className = 'navbar__logo--wrapper';
      tabletLogo.className = 'hide';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = '';
      mobileSearch.className = 'hide';
    },
    unmatch: function () {
      siteLogo.className = 'navbar__logo--wrapper';
      tabletLogo.className = 'hide';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = '';
      mobileSearch.className = 'hide';
    },
  }).register("screen and (max-width:960px)", {
    match: function () {
      siteLogo.className = 'hide';
      tabletLogo.className = '';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = 'hide';
      mobileSearch.className = 'navbar__icons--icon';
    },
    unmatch: function () {
      siteLogo.className = 'navbar__logo--wrapper';
      tabletLogo.className = 'hide';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = '';
      mobileSearch.className = 'hide';
    },
  }).register("screen and (max-width:600px)", {
    match: function () {
      siteLogo.className = 'hide';
      tabletLogo.className = 'hide';
      mobileLogo.className = '';
      navMenu.className = 'hide';
      navMenuMobile.className = '';
      siteSearch.className = 'hide';
      mobileSearch.className = 'navbar__icons--icon';
    },
    unmatch: function () {
      siteLogo.className = 'hide';
      tabletLogo.className = '';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = 'hide';
      mobileSearch.className = 'navbar__icons--icon';
    },
  });
</script>

        
  <div class="top">
  <div class="header__wrapper bgcolor__header">
    <div class="divider">
      <div class="lmr">
        <h2 class="title">zustand</h2>
      </div>
    </div>
  </div>

  <div class="header__wrapper bgcolor__breadcrumb">
    <div class="divider">
      <div class="lmr flexbox">
        
          <nav class="breadcrumb" aria-label="breadcrumbs" data-is-blog="false">
  
  <ol>
    
  
  
  
  
  
  <li >
    
      <a href="https://codthing.github.io/" class="capitalize">codthing</a>
    
  </li>
  
  
  <li >
    
      <a href="https://codthing.github.io/react/" class="capitalize">React</a>
    
  </li>
  
  
  <li  class="is-active" >
    
      <span>zustand</span>
    
  </li>
  
  </ol>
  
</nav>
        
        <div class="grow"></div>
        
  <label class="switch switch__rel">
    
      <input id="toggle-sidebar" aria-label="Toggle Sidebar Visibility" type="checkbox" checked />
      <span class="slider">
        <span class="slider__icon ">
          <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M5 13h11.17l-4.88 4.88c-.39.39-.39 1.03 0 1.42.39.39 1.02.39 1.41 0l6.59-6.59c.39-.39.39-1.02 0-1.41l-6.58-6.6c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L16.17 11H5c-.55 0-1 .45-1 1s.45 1 1 1z"/></svg>
        </span>
        <span class="slider__icon hide">
          <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42-.39-.39-1.02-.39-1.41 0l-6.59 6.59c-.39.39-.39 1.02 0 1.41l6.59 6.59c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1z"/></svg>
        </span>
      </span>
    
    
  </label>

        
      </div>
    </div>
  </div>
</div>

        
  

<div class="mid">
  <div class="divider">
    
    <nav id="single-menu" class="l" data-dir="ltr">
      
        <div class="menu">
  <h6 class="menu__label">
    
      zustand
    
  </h6>
  <ul>
    
    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/redux/react-redux/"
      class="menu__title ">React &amp; Redux</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/react/react-base/"
      class="menu__title ">React 基础</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/react/react-bp/"
      class="menu__title ">React 最佳实践</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/redux/redux-base/"
      class="menu__title ">Redux</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/hooks/hooks-bp/"
      class="menu__title ">Hooks 最佳实践</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/redux/hooks-redux/"
      class="menu__title ">Hooks &amp; Redux</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="active">
    <a href="https://codthing.github.io/react/zustand/zustand-base/"
      class="menu__title active">zustand</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/recoil/recoil-bp/"
      class="menu__title ">Recoil 最佳实践</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/next/">
    <span class="menu__title--collapse-text">
      Next.js
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/next/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/next/next-base/" class="menu__title " data-depth="0">Next.js 速览</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/next/next-content/" class="menu__title " data-depth="0">Next.js 核心工作内容</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/next/next-multiple/" class="menu__title " data-depth="0">Next.js 各种组合</a>
        </li>
      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/remix/remix-base/"
      class="menu__title ">Remix 基础</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="https://codthing.github.io/react/remix/remix-adv/"
      class="menu__title ">Remix 进阶</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/storybook/">
    <span class="menu__title--collapse-text">
      Storybook
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/storybook/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-bp/" class="menu__title " data-depth="0">Storybook 最佳实践</a>
        </li>
      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/storybook/sb-started/">
    <span class="menu__title--collapse-text">
      开始
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/sb-started/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-introduction/" class="menu__title " data-depth="1">介绍</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-install/" class="menu__title " data-depth="1">安装</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-what/" class="menu__title " data-depth="1">Story 是什么？</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-browse/" class="menu__title " data-depth="1">浏览故事</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-started/sb-setup/" class="menu__title " data-depth="1">设置</a>
        </li>
      
    
  </ul>
  

      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/storybook/sb-write/">
    <span class="menu__title--collapse-text">
      写故事
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/sb-write/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
  </ul>
  

      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/storybook/sb-test/">
    <span class="menu__title--collapse-text">
      编写测试
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/sb-test/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-test/sb-test-introduction/" class="menu__title " data-depth="1">介绍</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-test/sb-visual-tests/" class="menu__title " data-depth="1">视觉测试</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/storybook/sb-test/sb-accessibility-testing/" class="menu__title " data-depth="1">可访问性测试</a>
        </li>
      
    
  </ul>
  

      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/tailwindcss/">
    <span class="menu__title--collapse-text">
      tailwindcss
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/tailwindcss/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="https://codthing.github.io/react/tailwindcss/tailwindcss-start.md/">
    <span class="menu__title--collapse-text">
      开始
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/tailwindcss-start.md/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/tailwindcss/tailwindcss-start.md/tailwindcss-install/" class="menu__title " data-depth="1">安装</a>
        </li>
      
    
  </ul>
  

      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="https://codthing.github.io/react/wechat-mini/">
    <span class="menu__title--collapse-text">
      小程序开发
    </span>
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
  </li>
  <ul class="menu__list " data-data=/wechat-mini/ data-link=https://codthing.github.io/react/zustand/zustand-base/>
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/wechat-mini/taro-log/" class="menu__title " data-depth="0">Taro开发日志</a>
        </li>
      
    
      
        
        
        <li>
          <a href="https://codthing.github.io/react/wechat-mini/remax-log/" class="menu__title " data-depth="0">Remax开发日志</a>
        </li>
      
    
  </ul>
  

    
  </ul>
</div>


      
    </nav>

    <article id="list-main" class="m" data-dir="ltr">
      <div class="single" data-display="block">
  

  <article class="single__contents" data-dir="ltr">
    <p><p class="md__image">
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g464hzcxlgz4abbaeotc.png" alt="Image description"  />
</p></p>
<p><a href="https://github.com/pmndrs/zustand" target="_blank">zustand</a> 基于 hooks 的 api，小型、快速且可扩展的状态管理解决方案。</p>
<h2 id="一安装">一、安装</h2>
<pre tabindex="0"><code class="language-base" data-lang="base">yarn add zustand
</code></pre><h2 id="二最简使用方法">二、最简使用方法</h2>
<h3 id="step1-创建一个-store">Step1. 创建一个 Store</h3>
<p><code>store</code> 是一个钩子！ 可以在里面放任何东西：<code>原始数据（string，number，bigint，boolean，null）</code>、<code>对象</code>、<code>方法</code>。 <code>set</code> 方法合并状态。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">import create from &#39;zustand&#39;

const useCount = create(set =&gt; ({
  count: 0,
  plus: () =&gt; set(state =&gt; ({ count: state.count + 1 })),
  minus: () =&gt; set(state =&gt; ({ count: state.count - 1 })),
  reset: () =&gt; set({ count: 0 })
}))
</code></pre><h3 id="step2-绑定组件">Step2. 绑定组件</h3>
<pre tabindex="0"><code class="language-base" data-lang="base">function Counter() {
  const count = useCount(state =&gt; state.count)
  return &lt;h1&gt;{count}&lt;/h1&gt;
}

function Controls() {
  const plus = useCount(state =&gt; state.plus)
  const minus= useCount(state =&gt; state.minus)
  const reset= useCount(state =&gt; state.reset)

  return (
     &lt;&gt;
       &lt;button onClick={plus}&gt;+&lt;/button&gt;
       &lt;button onClick={minus}&gt;-&lt;/button&gt;
       &lt;button onClick={reset}&gt;重置&lt;/button&gt;
     &lt;/&gt;
  )
}
</code></pre><h2 id="二强制渲染组件">二、强制渲染组件</h2>
<p>记住，它会导致组件在每次状态更改时渲染！</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const state = useStore()
</code></pre><h2 id="三state-更新渲染组件">三、state 更新渲染组件</h2>
<p>切片状态（slice state）,因为store是一个原子状态，可以将它切分为多个格子状态，便于代码管理。</p>
<h3 id="1-单个-state-更新渲染">1. 单个 state 更新渲染</h3>
<p>默认情况下，它以严格相等（<code>旧 === 新</code>）检测更改，这对于原子状态选择非常有效。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const nuts = useStore(state =&gt; state.nuts)
const honey = useStore(state =&gt; state.honey)
</code></pre><h3 id="2-多个-state-更新浅差异渲染">2. 多个 state 更新（浅差异）渲染</h3>
<p>如果想构造一个内部有多个 state-picks(状态选择) 的单个对象，类似于 redux 的 mapStateToProps，可以告诉 zustand 你希望通过传递<code>shallow</code>相等函数来对对象进行浅差异。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">shallow</span> <span class="nx">from</span> <span class="s1">&#39;zustand/shallow&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 对象选择，当 `state.nuts` 或 `state.honey` 改变时重新渲染组件
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="p">{</span> <span class="nx">nuts</span><span class="p">,</span> <span class="nx">honey</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="p">({</span> <span class="nx">nuts</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">nuts</span><span class="p">,</span> <span class="nx">honey</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">honey</span> <span class="p">}),</span> <span class="nx">shallow</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 数组选择，当 `state.nuts` 或 `state.honey` 改变时重新渲染组件
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="p">[</span><span class="nx">nuts</span><span class="p">,</span> <span class="nx">honey</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="p">[</span><span class="nx">state</span><span class="p">.</span><span class="nx">nuts</span><span class="p">,</span> <span class="nx">state</span><span class="p">.</span><span class="nx">honey</span><span class="p">],</span> <span class="nx">shallow</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 映射选择，当 `state.treats` 按 `count` 或 `keys` 顺序改变时重新渲染组件
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">treats</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">state</span><span class="p">.</span><span class="nx">treats</span><span class="p">),</span> <span class="nx">shallow</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="3-自定义函数控制渲染">3. 自定义函数控制渲染</h3>
<p>为了更好地控制重新渲染，可以提供任何自定义的相等函数。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const treats = useStore(
  state =&gt; state.treats,
  (oldTreats, newTreats) =&gt; compare(oldTreats, newTreats)
)
</code></pre><h2 id="四记忆处理器避免重复计算">四、记忆处理器（避免重复计算）</h2>
<h3 id="1-usecallback-处理器">1. useCallback() 处理器</h3>
<p>通常建议使用 useCallback 记忆处理器。 这将防止每次渲染时进行不必要的计算。 它还允许 React 在并发模式下优化性能。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const fruit = useStore(useCallback(state =&gt; state.fruits[id], [id]))
</code></pre><h3 id="2-不依赖于作用域的处理器">2. 不依赖于作用域的处理器</h3>
<p>如果一个处理器不依赖于作用域，可以在渲染函数之外定义它以获得一个固定的“引用”而无需 useCallback。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const selector = state =&gt; state.berries

function Component() {
  const berries = useStore(selector)
}
</code></pre><h2 id="五覆盖state抹去之前的state">五、覆盖state（抹去之前的state）</h2>
<p><code>set</code> 函数有第二个参数，默认为 false。 它将取代<code>state</code>模型，而不是合并。 注意它会抹去你依赖的部分，比如<code>actions</code>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">omit</span> <span class="nx">from</span> <span class="s2">&#34;lodash-es/omit&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">set</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">salmon</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">tuna</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">deleteEverything</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">({</span> <span class="p">},</span> <span class="kc">true</span><span class="p">),</span> <span class="c1">// 清除整个存储，包括操作
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">deleteTuna</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="nx">omit</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;tuna&#39;</span><span class="p">]),</span> <span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="六异步操作fetch请求">六、异步操作（fetch请求）</h2>
<p>调用 <code>set</code> ， zustand 不关心操作是否异步。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const useStore = create(set =&gt; ({
  girls: {},
  fetch: async pond =&gt; {
    const response = await fetch(pond)
    set({ girls: await response.json() })
  }
}))
</code></pre><h2 id="七从-action-中读取-state">七、从 action 中读取 state</h2>
<p>通过<code>get</code>访问状态。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const useStore = create((set, get) =&gt; ({
  name: &#34;Lucy&#34;,
  action: () =&gt; {
    const name= get().name
    // ...
  }
})
</code></pre><h2 id="八在-react-组件之外读写-state">八、在 React 组件之外读写 state</h2>
<h3 id="1-自定义-hooks-读写-state">1. 自定义 hooks 读写 state</h3>
<p>有时需要以<code>非React</code>方式访问状态，或对<code>store</code>进行操作。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">({</span> <span class="nx">paw</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">snout</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">fur</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 在React组件之外获取state
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">paw</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">paw</span> <span class="c1">//true
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 侦听所有更改，在每次更改时同步触发
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">unsub</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">subscribe</span><span class="p">(</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 更新状态，将触发侦听器
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">useStore</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">paw</span><span class="o">:</span> <span class="kc">false</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 取消订阅侦听
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">unsub</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 销毁商店（删除所有侦听器）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">useStore</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 当然可以像hook一样使用
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">Component</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">paw</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="nx">state</span><span class="p">.</span><span class="nx">paw</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="2-使用订阅处理器中间件">2. 使用订阅处理器（中间件）</h3>
<p>如果您需要使用处理器订阅，<code>subscribeWithSelector</code> 中间件会有所帮助。</p>
<p>有了这个中间件，subscribe 接受一个额外的签名：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">subscribe(selector, callback, options?: { equalityFn, fireImmediately }): Unsubscribe
</code></pre><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">subscribeWithSelector</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;zustand/middleware&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">subscribeWithSelector</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">({</span> <span class="nx">paw</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">snout</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">fur</span><span class="o">:</span> <span class="kc">true</span> <span class="p">})))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 订阅状态值变化
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">unsub2</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">subscribe</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="nx">state</span><span class="p">.</span><span class="nx">paw</span><span class="p">,</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 订阅上一个状态值
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">unsub3</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">subscribe</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="nx">state</span><span class="p">.</span><span class="nx">paw</span><span class="p">,</span> <span class="p">(</span><span class="nx">paw</span><span class="p">,</span> <span class="nx">previousPaw</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">paw</span><span class="p">,</span> <span class="nx">previousPaw</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 订阅一个可选的浅差异方法
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">unsub4</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">subscribe</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="p">[</span><span class="nx">state</span><span class="p">.</span><span class="nx">paw</span><span class="p">,</span> <span class="nx">state</span><span class="p">.</span><span class="nx">fur</span><span class="p">],</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">,</span> <span class="p">{</span> <span class="nx">equalityFn</span><span class="o">:</span> <span class="nx">shallow</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 解除订阅
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">unsub5</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">subscribe</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="nx">state</span><span class="p">.</span><span class="nx">paw</span><span class="p">,</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">,</span> <span class="p">{</span> <span class="nx">fireImmediately</span><span class="o">:</span> <span class="kc">true</span> <span class="p">})</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="3-订阅处理器中间件使用ts">3. 订阅处理器（中间件）使用TS</h3>
<pre tabindex="0"><code class="language-base" data-lang="base">import create, { GetState, SetState } from &#39;zustand&#39;
import { StoreApiWithSubscribeWithSelector, subscribeWithSelector } from &#39;zustand/middleware&#39;

type BearState = {
  paw: boolean
  snout: boolean
  fur: boolean
}
const useStore = create&lt;
  BearState,
  SetState&lt;BearState&gt;,
  GetState&lt;BearState&gt;,
  StoreApiWithSubscribeWithSelector&lt;BearState&gt;
&gt;(subscribeWithSelector(() =&gt; ({ paw: true, snout: true, fur: true })))
</code></pre><h2 id="九瞬时更新ref用于频繁发生的状态变化">九、瞬时更新ref（用于频繁发生的状态变化）</h2>
<p>订阅功能允许组件绑定到state，而无需在更改时强制重新渲染。 <br />
最好将它与 <code>useEffect</code> 结合使用，以便在卸载时自动取消订阅。 <br />
当直接改变视图时，这会对性能产生巨大影响。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">const useStore = create(set =&gt; ({ girlNum: 0, ... }))

function Component() {
  // 获取初始状态
  const girlNumRef = useRef(useStore.getState().girlNum)
  // 在挂载时连接到Store，在卸载时断开连接，在引用时捕获状态变化
  useEffect(() =&gt; useStore.subscribe(
    state =&gt; (girlNumRef.current = state.girlNum)
  ), [])
</code></pre><h2 id="十更新嵌套的状态使用-immer">十、更新嵌套的状态，使用 Immer</h2>
<p>嵌套结构令人厌烦。 可以使用 Immer 处理深层嵌套的state</p>
<pre tabindex="0"><code class="language-base" data-lang="base">import produce from &#39;immer&#39;

const useStore = create(set =&gt; ({
  lush: { forest: { contains: { a: &#34;bear&#34; } } },
  clearForest: () =&gt; set(produce(state =&gt; {
    state.lush.forest.contains = null
  }))
}))

const clearForest = useStore(state =&gt; state.clearForest)
clearForest();
</code></pre><h2 id="十一中间件">十一、中间件</h2>
<h3 id="1-按自己喜欢的方式管理store">1. 按自己喜欢的方式管理store</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 记录每次改变的state
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">log</span> <span class="o">=</span> <span class="nx">config</span> <span class="p">=&gt;</span> <span class="p">(</span><span class="nx">set</span><span class="p">,</span> <span class="nx">get</span><span class="p">,</span> <span class="nx">api</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">config</span><span class="p">(</span><span class="nx">args</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;  applying&#34;</span><span class="p">,</span> <span class="nx">args</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">set</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;  new state&#34;</span><span class="p">,</span> <span class="nx">get</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span> <span class="nx">get</span><span class="p">,</span> <span class="nx">api</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 将 set 方法变成一个 immer proxy
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">immer</span> <span class="o">=</span> <span class="nx">config</span> <span class="p">=&gt;</span> <span class="p">(</span><span class="nx">set</span><span class="p">,</span> <span class="nx">get</span><span class="p">,</span> <span class="nx">api</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">config</span><span class="p">((</span><span class="nx">partial</span><span class="p">,</span> <span class="nx">replace</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">nextState</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">partial</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span>
</span></span><span class="line"><span class="cl">      <span class="o">?</span> <span class="nx">produce</span><span class="p">(</span><span class="nx">partial</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="o">:</span> <span class="nx">partial</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">set</span><span class="p">(</span><span class="nx">nextState</span><span class="p">,</span> <span class="nx">replace</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span> <span class="nx">get</span><span class="p">,</span> <span class="nx">api</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">log</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="nx">immer</span><span class="p">((</span><span class="nx">set</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">bees</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">setBees</span><span class="o">:</span> <span class="p">(</span><span class="nx">input</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="k">void</span> <span class="p">(</span><span class="nx">state</span><span class="p">.</span><span class="nx">bees</span> <span class="o">=</span> <span class="nx">input</span><span class="p">)),</span>
</span></span><span class="line"><span class="cl">    <span class="p">})),</span>
</span></span><span class="line"><span class="cl">  <span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="2-管理中间件">2. 管理中间件</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">create</span> <span class="nx">from</span> <span class="s2">&#34;zustand&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">produce</span> <span class="nx">from</span> <span class="s2">&#34;immer&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">pipe</span> <span class="nx">from</span> <span class="s2">&#34;ramda/es/pipe&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/* 上一个例子中的日志和immer函数 */</span>
</span></span><span class="line"><span class="cl"><span class="cm">/* 通过pipe集合任意数量的中间件 */</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">createStore</span> <span class="o">=</span> <span class="nx">pipe</span><span class="p">(</span><span class="nx">log</span><span class="p">,</span> <span class="nx">immer</span><span class="p">,</span> <span class="nx">create</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">createStore</span><span class="p">(</span><span class="nx">set</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">bears</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">increasePopulation</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="p">({</span> <span class="nx">bears</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">bears</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">}))</span>
</span></span><span class="line"><span class="cl"><span class="p">}))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="nx">useStore</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="3-在管理中间件中使用ts">3. 在管理中间件中使用TS</h3>
<pre tabindex="0"><code>yarn add --dev @types/ramda
</code></pre><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">create</span> <span class="kr">from</span> <span class="s2">&#34;zustand&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">devtools</span><span class="p">,</span> <span class="nx">redux</span> <span class="p">}</span> <span class="kr">from</span> <span class="s2">&#34;zustand/middleware&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">pipe</span> <span class="kr">from</span> <span class="s2">&#34;ramda/es/pipe&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">log</span>: <span class="kt">typeof</span> <span class="nx">devtools</span> <span class="o">=</span> <span class="nx">config</span> <span class="o">=&gt;</span> <span class="p">(</span><span class="kr">set</span><span class="p">,</span> <span class="kr">get</span><span class="p">,</span> <span class="nx">api</span><span class="p">)</span> <span class="o">=&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">config</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="nx">args</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;  applying&#34;</span><span class="p">,</span> <span class="nx">args</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="kr">set</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;  new state&#34;</span><span class="p">,</span> <span class="kr">get</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="kr">get</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">api</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">type</span> <span class="nx">State</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">grumpiness</span>: <span class="kt">number</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">initialState</span>: <span class="kt">State</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">grumpiness</span>: <span class="kt">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">createStore</span> <span class="o">=</span> <span class="nx">pipe</span><span class="p">(</span><span class="nx">redux</span><span class="p">,</span> <span class="nx">devtools</span><span class="p">,</span> <span class="nx">log</span><span class="p">,</span> <span class="nx">create</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">enum</span> <span class="nx">types</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">increase</span> <span class="o">=</span> <span class="s2">&#34;INCREASE&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">decrease</span> <span class="o">=</span> <span class="s2">&#34;DECREASE&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">reducer</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">state</span>: <span class="kt">State</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="kr">type</span><span class="p">,</span> <span class="nx">by</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">}</span><span class="o">:</span> <span class="p">{</span> <span class="kr">type</span><span class="o">:</span> <span class="nx">types</span><span class="p">;</span> <span class="nx">by</span>: <span class="kt">number</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">switch</span> <span class="p">(</span><span class="kr">type</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nx">types.increase</span>:
</span></span><span class="line"><span class="cl">      <span class="kt">return</span> <span class="p">{</span> <span class="nx">grumpiness</span>: <span class="kt">state.grumpiness</span> <span class="o">+</span> <span class="nx">by</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nx">types.decrease</span>:
</span></span><span class="line"><span class="cl">      <span class="kt">return</span> <span class="p">{</span> <span class="nx">grumpiness</span>: <span class="kt">state.grumpiness</span> <span class="o">-</span> <span class="nx">by</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">createStore</span><span class="p">(</span><span class="nx">reducer</span><span class="p">,</span> <span class="nx">initialState</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="nx">useStore</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="十二状态持久化中间件-persist">十二、状态持久化中间件 persist</h2>
<p>可以存储任何类型的store数据。（localStorage，AsyncStorage，IndexedDB，等&hellip;）</p>
<h3 id="1-快速示例">1. 快速示例</h3>
<pre tabindex="0"><code class="language-base" data-lang="base">import create from &#34;zustand&#34;
import { persist } from &#34;zustand/middleware&#34;

export const useStore = create(persist(
  (set, get) =&gt; ({
    count: 0,
    plus: () =&gt; set({ count: get().count + 1 })
  }),
  {
    name: &#34;count-storage&#34;, // 唯一的名称
    getStorage: () =&gt; sessionStorage, // （可选）默认情况下，使用“localStorage”
  }
))
</code></pre><h3 id="2-选项">2. 选项</h3>
<ol>
<li>
<p><code>name</code> 这是唯一需要的选项。给定的<code>名称</code>将是用于存储<code>state</code>的键，因此它必须是<code>唯一</code>的。</p>
</li>
<li>
<p><code>getStorage</code> 默认： <code>() =&gt; localStorage</code></p>
</li>
</ol>
<p>给定的存储必须与以下接口匹配：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Storage</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">getItem</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span>: <span class="kt">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="kt">string</span> <span class="o">|</span> <span class="kc">null</span> <span class="o">|</span> <span class="nx">Promise</span><span class="p">&lt;</span><span class="nt">string</span> <span class="err">|</span> <span class="na">null</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">setItem</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span>: <span class="kt">string</span><span class="p">,</span> <span class="nx">value</span>: <span class="kt">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="o">|</span> <span class="nx">Promise</span><span class="p">&lt;</span><span class="nt">void</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">removeItem</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span>: <span class="kt">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="o">|</span> <span class="nx">Promise</span><span class="p">&lt;</span><span class="nt">void</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="3">
<li><code>serialize</code>（序列化）</li>
</ol>
<ul>
<li>Schema: <code>(state: Object) =&gt; string | Promise&lt;string&gt;</code></li>
<li>Default: <code>(state) =&gt; JSON.stringify(state)</code></li>
</ul>
<p>由于将对象存储在 storage 中的唯一方法是通过字符串，可以使用此选项提供自定义函数将 state 序列化为字符串。</p>
<p>例如，如果您想将 state 存储在 base64 中：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">export const useStore = create(persist(
  (set, get) =&gt; ({
    // ...
  }),
  {
    // ...
    serialize: (state) =&gt; btoa(JSON.stringify(state)),
  }
))
</code></pre><p>请注意，还需要一个自定义<code>deserialize</code>函数才能使其正常工作。见下文</p>
<ol start="4">
<li><code>deserialize</code> （反序列化）</li>
</ol>
<ul>
<li>Schema: <code>(str: string) =&gt; Object | Promise&lt;Object&gt;</code></li>
<li>Default: <code>(str) =&gt; JSON.parse(str)</code></li>
</ul>
<p>如果使用自定义序列化函数，则很可能还需要使用自定义反序列化函数。它们是一对搭档。</p>
<p>要继续上面的示例，可以使用以下命令反序列化 base64 值：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">export const useStore = create(persist(
  (set, get) =&gt; ({
    // ...
  }),
  {
    // ...
    deserialize: (str) =&gt; JSON.parse(atob(str)),
  }
))
</code></pre><ol start="5">
<li><code>partialize</code> (初始化部分state)</li>
</ol>
<ul>
<li>Schema: <code>(state: Object) =&gt; Object</code></li>
<li>Default: <code>(state) =&gt; state</code></li>
</ul>
<p>它够省略一些要存储在 storage 中的 state 字段。</p>
<p>可以使用以下方法省略多个字段：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">export const useStore = create(persist(
  (set, get) =&gt; ({
    foo: 0,
    bar: 1,
  }),
  {
    // ...
    partialize: (state) =&gt;
      Object.fromEntries(
        Object.entries(state).filter(([key]) =&gt; ![&#34;foo&#34;].includes(key))
      ),
  }
))
</code></pre><p>或者只允许存储特定state字段：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">export const useStore = create(persist(
  (set, get) =&gt; ({
    foo: 0,
    bar: 1,
  }),
  {
    // ...
    partialize: (state) =&gt; ({ foo: state.foo })
  }
))
</code></pre><ol start="6">
<li><code>onRehydrateStorage</code> （水和存储）</li>
</ol>
<ul>
<li>Schema: <code>(state: Object) =&gt; ((state?: Object, error?: Error) =&gt; void) | void</code></li>
</ul>
<p>此选项能够在<code>水合存储</code>时调用的侦听器函数。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">persist</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nx">set</span><span class="p">,</span> <span class="nx">get</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">onRehydrateStorage</span><span class="o">:</span> <span class="p">(</span><span class="nx">state</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;hydration starts&#34;</span><span class="p">);</span> <span class="c1">//水合开始
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			
</span></span><span class="line"><span class="cl">      <span class="c1">// 可选
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">return</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">error</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;an error happened during hydration&#34;</span><span class="p">,</span> <span class="nx">error</span><span class="p">)</span> <span class="c1">//水合过程中发生错误
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;hydration finished&#34;</span><span class="p">)</span> <span class="c1">//水合完成
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="7">
<li><code>version</code> 指定存储版本</li>
</ol>
<ul>
<li>Schema: <code>number</code></li>
<li>Default: <code>0</code></li>
</ul>
<p>如果在 storage 中引入重大更改（例如重命名字段），可以指定新版本号。<br />
默认情况下，如果 storage 中的版本与代码中的版本不匹配，则不会使用 storage 的值。</p>
<p>有关处理重大更改的更多详细信息，请参阅下面的选项<code>migrate</code></p>
<ol start="8">
<li><code>migrate</code> 版本迁移</li>
</ol>
<ul>
<li>Schema: <code>(persistedState: Object, version: number) =&gt; Object | Promise&lt;Object&gt;</code></li>
<li>Default: <code>(persistedState) =&gt; persistedState</code></li>
</ul>
<p>可以使用此选项来处理版本迁移。migrate 函数将持久化state和版本号作为参数。<br />
它必须返回符合最新版本（代码中的版本）的state。</p>
<p>例如，如果要重命名字段，可以使用以下命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">persist</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nx">set</span><span class="p">,</span> <span class="nx">get</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">newField</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="c1">// 假设该字段在版本 0 中以其他方式命名
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">version</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="c1">// 如果 storage 中的版本与此迁移不匹配，则会触发：
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">migrate</span><span class="o">:</span> <span class="p">(</span><span class="nx">persistedState</span><span class="p">,</span> <span class="nx">version</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">version</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 如果存储的值在版本为 0 ，则将该字段重命名为新名称
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">persistedState</span><span class="p">.</span><span class="nx">newField</span> <span class="o">=</span> <span class="nx">persistedState</span><span class="p">.</span><span class="nx">oldField</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">delete</span> <span class="nx">persistedState</span><span class="p">.</span><span class="nx">oldField</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">      
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">persistedState</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="9">
<li><code>merge</code> 合并存储值和state</li>
</ol>
<ul>
<li>
<p>Schema: <code>(persistedState: Object, currentState: Object) =&gt; Object</code></p>
</li>
<li>
<p>Default: <code>(persistedState, currentState) =&gt; ({ ...currentState, ...persistedState })</code></p>
</li>
</ul>
<p>在某些情况下，希望使用自定义合并函数将持久值与当前状态合并。</p>
<p>默认情况下，中间件进行<code>浅合并</code>。如果部分持久化了嵌套对象，那么浅层合并可能还不够。</p>
<p>例如，如果存储包含以下内容：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">{
  foo: {
    bar: 0,
  }
}
</code></pre><p>但是你的 Zustand store 包含:</p>
<pre tabindex="0"><code class="language-base" data-lang="base">{
  foo: {
    bar: 0,
    baz: 1,
  }
}
</code></pre><p>浅合并将从对象 foo 中擦除 baz 字段。解决此问题的一种方法是提供<code>自定义深度</code>合并功能：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">export const useStore = create(persist(
  (set, get) =&gt; ({
    foo: {
      bar: 0,
      baz: 1,
    },
  }),
  {
    // ...
    merge: (persistedState, currentState) =&gt; deepMerge(currentState, persistedState),
  }
))
</code></pre><h3 id="3-api">3. API</h3>
<p>persist api 使 React 组件的内部或外部与持久中间件进行大量交互。</p>
<ol>
<li><code>setOptions</code> 更改中间件选项</li>
</ol>
<ul>
<li>Schema: <code>(newOptions: PersistOptions) =&gt; void</code></li>
</ul>
<p>此方法能够更改中间件选项。请注意，新选项将与当前选项合并。</p>
<p>例如，这可用于更改 storage 名称：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">useStore.persist.setOptions({
  name: &#34;new-name&#34;
});
</code></pre><p>甚至更改 storage 引擎：</p>
<pre tabindex="0"><code class="language-base" data-lang="base">useStore.persist.setOptions({
  getStorage: () =&gt; sessionStorage,
});
</code></pre><ol start="2">
<li><code>clearStorage</code></li>
</ol>
<ul>
<li>Schema: <code>() =&gt; void</code></li>
</ul>
<p>这可用于完全清除 storage 中的持久值。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">useStore.persist.clearStorage();
</code></pre><ol start="3">
<li><code>rehydrate</code> 触发水合</li>
</ol>
<ul>
<li>Schema: <code>() =&gt; Promise&lt;void&gt;</code></li>
</ul>
<p>在某些情况下，可能希望手动触发水合。可以通过调用该<code>rehydrate</code>方法来完成。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">await useStore.persist.rehydrate();
</code></pre><ol start="4">
<li><code>hasHydrated</code> 获取水合状态</li>
</ol>
<ul>
<li>Schema: <code>() =&gt; boolean</code></li>
</ul>
<p>这是一个React的 getter，用于了解存储是否已被水合（请注意，在调用<code>useStore.persist.rehydrate()</code>时会更新）。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">useStore.persist.hasHydrated();
</code></pre><ol start="5">
<li><code>onHydrate</code> 水合过程开始</li>
</ol>
<ul>
<li>Schema: <code>(listener: (state) =&gt; void) =&gt; () =&gt; void</code></li>
</ul>
<p>水合过程开始时将调用给定的侦听器。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">unsub</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">persist</span><span class="p">.</span><span class="nx">onHydrate</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;hydration starts&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 稍后...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">unsub</span><span class="p">();</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="6">
<li><code>onFinishHydration</code> 水合过程结束</li>
</ol>
<ul>
<li>Schema: <code>(listener: (state) =&gt; void) =&gt; () =&gt; void</code></li>
</ul>
<p>当水化过程结束时，将调用给定的侦听器。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">unsub</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">.</span><span class="nx">persist</span><span class="p">.</span><span class="nx">onFinishHydration</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;hydration finished&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 稍后...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">unsub</span><span class="p">();</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="4-水合和异步存储">4. 水合和异步存储</h3>
<p>要解释异步存储的“成本”是什么，需要了解什么是<code>水合作用（hydration</code>）。</p>
<h4 id="1-什么是水合hydration">1). 什么是水合hydration？</h4>
<p><strong>简而言之，水合是从 storage 中检索持久状态并将其与当前状态合并的过程。</strong></p>
<p>persist 中间件执行两种 <code>水合hydration</code>：同步和异步。<br />
如果给定的存储是同步的（例如localStorage），水合将同步完成，如果给定的存储是异步的（例如AsyncStorage），水合将异步完成&hellip;&hellip;🥁。</p>
<p>但问题是什么？ <br />
在同步水合中，Zustand 在创建 store 时进行水合。在异步水合中，Zustand store 将在稍后的微任务中水合。</p>
<p>为什么这有关系？ <br />
<code>异步水合可能会导致一些意外行为</code>（成本所在）。例如，<br />
如果在 React 应用程序中使用 Zustand，store 将不会在初始渲染时水合。<br />
如果应用程序依赖于页面加载时的持久值，你可能希望等到 store 已被水合后再显示内容<br />
（例如，应用程序可能认为用户未登录，因为这是默认值，而实际上 store 还没有被水合）。</p>
<h4 id="2-如何检查-store-是否已水合">2). 如何检查 store 是否已水合</h4>
<p>有几种不同的方法可以做到这一点。</p>
<p><strong>fn1. 可以使用<code>onRehydrateStorage</code>选项来更新 store 中的字段：</strong></p>
<pre tabindex="0"><code class="language-base" data-lang="base">const useStore = create(
  persist(
    (set, get) =&gt; ({
      // ...
      _hasHydrated: false
    }),
    {
      // ...
      onRehydrateStorage: () =&gt; () =&gt; {
        useStore.setState({ _hasHydrated: true })
      }
    }
  )
);

export default function App() {
  const hasHydrated = useStore(state =&gt; state._hasHydrated);

  if (!hasHydrated) {
    return &lt;p&gt;Loading...&lt;/p&gt;
  }

  return (
    // ...
  );
}
</code></pre><p><strong>fn2. 还可以创建自定义<code>useHydration</code>hook：</strong></p>
<pre tabindex="0"><code class="language-base" data-lang="base">const useStore = create(persist(...))

const useHydration = () =&gt; {
  const [hydrated, setHydrated] = useState(useStore.persist.hasHydrated)
  
  useEffect(() =&gt; {
    const unsubHydrate = useStore.persist.onHydrate(() =&gt; setHydrated(false)) // Note: this is just in case you want to take into account manual rehydrations. You can remove this if you don&#39;t need it/don&#39;t want it.
    const unsubFinishHydration = useStore.persist.onFinishHydration(() =&gt; setHydrated(true))
    
    setHydrated(useStore.persist.hasHydrated())
    
    return () =&gt; {
      unsubHydrate()
      unsubFinishHydration()
    }
  }, [])
  
  return hydrated
}
</code></pre><h3 id="5-如何使用自定义存储引擎">5. 如何使用自定义存储引擎？</h3>
<p>如果要使用的存储与预期的 API 不匹配，可以创建自己的存储：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">create</span> <span class="nx">from</span> <span class="s2">&#34;zustand&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">persist</span><span class="p">,</span> <span class="nx">StateStorage</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;zustand/middleware&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">get</span><span class="p">,</span> <span class="nx">set</span><span class="p">,</span> <span class="nx">del</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;idb-keyval&#39;</span> <span class="c1">// 可以使用任何东西：IndexedDB、Ionic Storage 等
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 自定义 storage 对象
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">storage</span><span class="o">:</span> <span class="nx">StateStorage</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">getItem</span><span class="o">:</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">name</span><span class="o">:</span> <span class="nx">string</span><span class="p">)</span><span class="o">:</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">string</span> <span class="o">|</span> <span class="kc">null</span><span class="o">&gt;</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="s2">&#34;has been retrieved&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="kr">await</span> <span class="nx">get</span><span class="p">(</span><span class="nx">name</span><span class="p">))</span> <span class="o">||</span> <span class="kc">null</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">setItem</span><span class="o">:</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">name</span><span class="o">:</span> <span class="nx">string</span><span class="p">,</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">string</span><span class="p">)</span><span class="o">:</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="k">void</span><span class="o">&gt;</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="s2">&#34;with value&#34;</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="s2">&#34;has been saved&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">set</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">removeItem</span><span class="o">:</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">name</span><span class="o">:</span> <span class="nx">string</span><span class="p">)</span><span class="o">:</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="k">void</span><span class="o">&gt;</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="s2">&#34;has been deleted&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">del</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">persist</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nx">set</span><span class="p">,</span> <span class="nx">get</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fishes</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">addAFish</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">({</span> <span class="nx">fishes</span><span class="o">:</span> <span class="nx">get</span><span class="p">().</span><span class="nx">fishes</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;food-storage&#34;</span><span class="p">,</span> <span class="c1">//唯一名称
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">getStorage</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">storage</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="十三像-redux-一样编写代码">十三、像 Redux 一样编写代码</h2>
<pre tabindex="0"><code class="language-base" data-lang="base">const types = { increase: &#34;INCREASE&#34;, decrease: &#34;DECREASE&#34; }

const reducer = (state, { type, by = 1 }) =&gt; {
  switch (type) {
    case types.increase: return { grumpiness: state.grumpiness + by }
    case types.decrease: return { grumpiness: state.grumpiness - by }
  }
}

const useStore = create(set =&gt; ({
  grumpiness: 0,
  dispatch: args =&gt; set(state =&gt; reducer(state, args)),
}))

const dispatch = useStore(state =&gt; state.dispatch)
dispatch({ type: types.increase, by: 2 })
</code></pre><p>或者，只需使用<code>redux-middleware</code>。</p>
<p>它连接你的<code>main-reducer</code>，设置初始 state，并向 state 本身和 vanilla api 添加一个<code>dispatch</code>函数。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">useEffect</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;react&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">ReactDOM</span> <span class="nx">from</span> <span class="s1">&#39;react-dom&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">create</span> <span class="nx">from</span> <span class="s1">&#39;zustand&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">devtools</span><span class="p">,</span> <span class="nx">redux</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;zustand/middleware&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="s1">&#39;./styles.css&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">initialState</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">count</span><span class="o">:</span> <span class="mi">0</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">types</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">increase</span><span class="o">:</span> <span class="s1">&#39;INCREASE&#39;</span><span class="p">,</span> <span class="nx">decrease</span><span class="o">:</span> <span class="s1">&#39;DECREASE&#39;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">reducer</span> <span class="o">=</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="p">{</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">by</span> <span class="p">})</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">switch</span> <span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nx">types</span><span class="p">.</span><span class="nx">increase</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="p">{</span> <span class="nx">count</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">+</span> <span class="nx">by</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nx">types</span><span class="p">.</span><span class="nx">decrease</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="p">{</span> <span class="nx">count</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">-</span> <span class="nx">by</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">default</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">[</span><span class="nx">useStore</span><span class="p">,</span> <span class="nx">api</span><span class="p">]</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// 将 store 连接到 devtools
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// 如果没有 reducers 和 action-types，你会看到“setState”被注销
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">devtools</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 将我们的 store 转换为 redux action dispatcher ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// 向 store 添加一个 dispatch 方法
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">redux</span><span class="p">(</span><span class="nx">reducer</span><span class="p">,</span> <span class="nx">initialState</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">Counter</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">count</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">useEffect</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Increase
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">setTimeout</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">api</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">types</span><span class="p">.</span><span class="nx">increase</span><span class="p">,</span> <span class="nx">by</span><span class="o">:</span> <span class="mi">3</span> <span class="p">}),</span> <span class="mi">1000</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Decrease
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">setTimeout</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">api</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">types</span><span class="p">.</span><span class="nx">decrease</span><span class="p">,</span> <span class="nx">by</span><span class="o">:</span> <span class="mi">1</span> <span class="p">}),</span> <span class="mi">2000</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Decrease
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">setTimeout</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">api</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">types</span><span class="p">.</span><span class="nx">decrease</span><span class="p">,</span> <span class="nx">by</span><span class="o">:</span> <span class="mi">1</span> <span class="p">}),</span> <span class="mi">3000</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span> <span class="p">[])</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">span</span> <span class="kr">class</span><span class="o">=</span><span class="s2">&#34;header&#34;</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">count</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/span&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">Counter</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;root&#39;</span><span class="p">))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="十四在-react-事件处理程序之外调用-actions">十四、在 React 事件处理程序之外调用 actions</h2>
<p>如果在 React 事件处理程序之外调用<code>setState</code>，它会同步处理。<br />
在事件处理程序之外更新状态将强制 react 同步更新组件，因此增加了遇到僵尸子效应的风险。<br />
为了解决这个问题，需要将 actions 包裹在<code>unstable_batchedUpdates</code>中。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">import { unstable_batchedUpdates } from &#39;react-dom&#39; // or &#39;react-native&#39;

const useStore = create((set) =&gt; ({
  fishes: 0,
  increaseFishes: () =&gt; set((prev) =&gt; ({ fishes: prev.fishes + 1 }))
}))

const nonReactCallback = () =&gt; {
  unstable_batchedUpdates(() =&gt; {
    useStore.getState().increaseFishes()
  })
}
</code></pre><h2 id="十五使用-redux-开发工具">十五、使用 Redux 开发工具</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">devtools</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;zustand/middleware&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 使用普通操作存储，它将记录操作为“setState”
</span></span></span><span class="line"><span class="cl"><span class="c1">// devtools 将只记录来自每个单独存储的操作，这与典型的 redux 存储不同
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">devtools</span><span class="p">(</span><span class="nx">store</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 使用 redux 存储，它将记录完整操作类型
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">devtools</span><span class="p">(</span><span class="nx">redux</span><span class="p">(</span><span class="nx">reducer</span><span class="p">,</span> <span class="nx">initialState</span><span class="p">)))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Name store: <code>devtools(store, {name: &quot;MyStore&quot;})</code>，这将在 devtools 中创建一个名为“MyStore”的单独实例。<br />
序列化选项：<code>devtools(store, { serialize: { options: true } })</code>。</p>
<h2 id="十六react-context">十六、React context</h2>
<p>store <code>create</code> 不需要上下文提供程序（context providers）。<br />
在某些情况下，你可能希望使用上下文进行依赖注入，或者如果你想使用组件中的 props 初始化 store。<br />
因为 store 是一个钩子，把它作为一个普通的上下文值传递可能会违反钩子的规则。<br />
为了避免误用，提供了一个特殊<code>createContext</code>。</p>
<h3 id="1-创建-createcontext">1. 创建 createContext</h3>
<pre tabindex="0"><code class="language-base" data-lang="base">import create from &#39;zustand&#39;
import createContext from &#39;zustand/context&#39;

const { Provider, useStore } = createContext()

const createStore = () =&gt; create(...)

const App = () =&gt; (
  &lt;Provider createStore={createStore}&gt;
    ...
  &lt;/Provider&gt;
)

const Component = () =&gt; {
  const state = useStore()
  const slice = useStore(selector)
  ...
}
</code></pre><h3 id="2-在组件中使用">2. 在组件中使用</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">create</span> <span class="nx">from</span> <span class="s2">&#34;zustand&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">createContext</span> <span class="nx">from</span> <span class="s2">&#34;zustand/context&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 最佳实践：可以将下面的 createContext() 和 createStore 移动到单独的文件 (store.js) 并导入提供程序Provider，在此处/任何需要的地方使用 store。
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">Provider</span><span class="p">,</span> <span class="nx">useStore</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">createContext</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">createStore</span> <span class="o">=</span> <span class="p">()</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">create</span><span class="p">((</span><span class="nx">set</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">bears</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">increasePopulation</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span> <span class="nx">bears</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">bears</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">})),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">removeAllBears</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">({</span> <span class="nx">bears</span><span class="o">:</span> <span class="mi">0</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="p">}));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">Button</span> <span class="o">=</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span><span class="cm">/** store() - 每次使用 Button 组件都创建一个 store，而不是为所有组件使用一个 store **/</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="nx">Provider</span> <span class="nx">createStore</span><span class="o">=</span><span class="p">{</span><span class="nx">createStore</span><span class="p">}</span><span class="o">&gt;</span> 
</span></span><span class="line"><span class="cl">      <span class="o">&lt;</span><span class="nx">ButtonChild</span> <span class="o">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="err">/Provider&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">ButtonChild</span> <span class="o">=</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">state</span> <span class="o">=</span> <span class="nx">useStore</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">bears</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="o">&lt;</span><span class="nx">button</span>
</span></span><span class="line"><span class="cl">        <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">state</span><span class="p">.</span><span class="nx">increasePopulation</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="p">}}</span>
</span></span><span class="line"><span class="cl">      <span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="o">+</span>
</span></span><span class="line"><span class="cl">      <span class="o">&lt;</span><span class="err">/button&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="err">/div&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="kd">function</span> <span class="nx">App</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">&#34;App&#34;</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="o">&lt;</span><span class="nx">Button</span> <span class="o">/&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="o">&lt;</span><span class="nx">Button</span> <span class="o">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="err">/div&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="3-createcontext-使用-props-初始化在-ts-中">3. createContext 使用 props 初始化（在 TS 中）</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">create</span> <span class="nx">from</span> <span class="s2">&#34;zustand&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">createContext</span> <span class="nx">from</span> <span class="s2">&#34;zustand/context&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">type</span> <span class="nx">BearState</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">bears</span><span class="o">:</span> <span class="nx">number</span>
</span></span><span class="line"><span class="cl">  <span class="nx">increase</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="k">void</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 将类型传递给 `createContext` 而不是 `create`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="p">{</span> <span class="nx">Provider</span><span class="p">,</span> <span class="nx">useStore</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">createContext</span><span class="o">&lt;</span><span class="nx">BearState</span><span class="o">&gt;</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="kd">function</span> <span class="nx">App</span><span class="p">({</span> <span class="nx">initialBears</span> <span class="p">}</span><span class="o">:</span> <span class="p">{</span> <span class="nx">initialBears</span><span class="o">:</span> <span class="nx">number</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="nx">Provider</span>
</span></span><span class="line"><span class="cl">      <span class="nx">createStore</span><span class="o">=</span><span class="p">{()</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nx">create</span><span class="p">((</span><span class="nx">set</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">          <span class="nx">bears</span><span class="o">:</span> <span class="nx">initialBears</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">increase</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span> <span class="nx">bears</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">bears</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">})),</span>
</span></span><span class="line"><span class="cl">        <span class="p">}))</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="o">&lt;</span><span class="nx">Button</span> <span class="o">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span><span class="err">/Provider&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="十七typescript-类型定义">十七、TypeScript 类型定义</h2>
<h3 id="1-类型定义">1. 类型定义</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 可以使用 `type`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">type</span> <span class="nx">BearState</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">bears</span><span class="o">:</span> <span class="nx">number</span>
</span></span><span class="line"><span class="cl">  <span class="nx">increase</span><span class="o">:</span> <span class="p">(</span><span class="nx">by</span><span class="o">:</span> <span class="nx">number</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="k">void</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 或者 `interface`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">interface</span> <span class="nx">BearState</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">bears</span><span class="o">:</span> <span class="nx">number</span>
</span></span><span class="line"><span class="cl">  <span class="nx">increase</span><span class="o">:</span> <span class="p">(</span><span class="nx">by</span><span class="o">:</span> <span class="nx">number</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="k">void</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 它对两者都有效
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">useStore</span> <span class="o">=</span> <span class="nx">create</span><span class="o">&lt;</span><span class="nx">BearState</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">set</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">bears</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">increase</span><span class="o">:</span> <span class="p">(</span><span class="nx">by</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">set</span><span class="p">(</span><span class="nx">state</span> <span class="p">=&gt;</span> <span class="p">({</span> <span class="nx">bears</span><span class="o">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">bears</span> <span class="o">+</span> <span class="nx">by</span> <span class="p">})),</span>
</span></span><span class="line"><span class="cl"><span class="p">}))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="2-使用combine-并让-tsc-推断类型">2. 使用<code>combine</code> 并让 tsc 推断类型</h3>
<p>这将两个状态浅合并。</p>
<pre tabindex="0"><code class="language-base" data-lang="base">import { combine } from &#39;zustand/middleware&#39;

const useStore = create(
  combine(
    { bears: 0 },
    (set) =&gt; ({ increase: (by: number) =&gt; set((state) =&gt; ({ bears: state.bears + by })) })
  ),
)
</code></pre><h2 id="十八最佳实践将store拆分为单独的slice">十八、最佳实践（将store拆分为单独的slice）</h2>
<blockquote>
<p>目录结构</p>
</blockquote>
<p><p class="md__image">
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/setcy553lsj3svmu7tu6.png" alt="Image description"  />
</p></p>
<blockquote>
<p>1.store/createBearSlice.js</p>
</blockquote>
<pre tabindex="0"><code class="language-base" data-lang="base">const createBearSlice = (set, get) =&gt; ({
  eatFish: () =&gt; {
    set((prev) =&gt; ({ fishes: prev.fishes &gt; 1 ? prev.fishes - 1 : 0 }));
  }
});

export default createBearSlice;
</code></pre><blockquote>
<p>2.store/createFishSlice.js</p>
</blockquote>
<pre tabindex="0"><code class="language-base" data-lang="base">const maxFishes = 10;

const createFishSlice = (set, get) =&gt; ({
  fishes: maxFishes,
  repopulate: () =&gt; {
    set((prev) =&gt; ({ fishes: maxFishes }));
  }
});

export default createFishSlice;
</code></pre><blockquote>
<p>3.store/createHoneySlice.js</p>
</blockquote>
<pre tabindex="0"><code class="language-base" data-lang="base">const createHoneySlice = (set, get) =&gt; ({
  honeySlice: {
    honey: 4
  }
});

export default createHoneySlice;
</code></pre><blockquote>
<p>4.store/useStore.js</p>
</blockquote>
<pre tabindex="0"><code class="language-base" data-lang="base">import create from &#34;zustand&#34;;

import createBearSlice from &#34;./createBearSlice&#34;;
import createFishSlice from &#34;./createFishSlice&#34;;
import createHoneySlice from &#34;./createHoneySlice&#34;;

const useStore = create((set, get) =&gt; ({
  ...createBearSlice(set, get),
  ...createHoneySlice(set, get),
  ...createFishSlice(set, get)
}));

export default useStore;
</code></pre><blockquote>
<p>5.pages/Mountain.js</p>
</blockquote>
<pre tabindex="0"><code class="language-base" data-lang="base">import useStore from &#34;../store/useStore&#34;;

export default function Mountain() {
  const fishes = useStore((state) =&gt; state.fishes);
  const eatFish = useStore((state) =&gt; state.eatFish);
  const repopulate = useStore((state) =&gt; state.repopulate);
  const honey = useStore((state) =&gt; state.honeySlice.honey);

  return (
    &lt;div className=&#34;Mountain&#34;&gt;
      &lt;p&gt;Fishes : {fishes}&lt;/p&gt;
      &lt;p&gt;honey : {honey}&lt;/p&gt;
      &lt;p&gt;
        &lt;button onClick={eatFish}&gt;Eat&lt;/button&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;button onClick={repopulate}&gt;Repopulate&lt;/button&gt;
      &lt;/p&gt;
    &lt;/div&gt;
  );
}
</code></pre>
  </article>
</div>
      
<div class="grow"></div>
<nav class="pagination-single">
  
    
      <a href="https://codthing.github.io/react/redux/hooks-redux/" title="Hooks &amp; Redux" class="pagination-single__left">
        <div class="pagination-single__icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42-.39-.39-1.02-.39-1.41 0l-6.59 6.59c-.39.39-.39 1.02 0 1.41l6.59 6.59c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1z"/></svg>
        </div>
        <div class="pagination-single__right-title">Hooks &amp; Redux</div>
      </a>
    
    <div class="grow"></div>
    
      <a href="https://codthing.github.io/react/recoil/recoil-bp/" title="Recoil 最佳实践" class="pagination-single__right">
        <div class="pagination-single__left-title">Recoil 最佳实践</div>
        <div class="pagination-single__icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M5 13h11.17l-4.88 4.88c-.39.39-.39 1.03 0 1.42.39.39 1.02.39 1.41 0l6.59-6.59c.39-.39.39-1.02 0-1.41l-6.58-6.6c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L16.17 11H5c-.55 0-1 .45-1 1s.45 1 1 1z"/></svg>
        </div>
      </a>
    
  
</nav>


      
  

    </article>
    
    <section id="list-side" class="r" data-dir="ltr">
      
        <div class="toc">
  <h6 class="toc__label">此页面上有什么</h6>
  <div class="toc__body">
    <nav id="TableOfContents">
  <ul>
    <li><a href="#一安装">一、安装</a></li>
    <li><a href="#二最简使用方法">二、最简使用方法</a>
      <ul>
        <li><a href="#step1-创建一个-store">Step1. 创建一个 Store</a></li>
        <li><a href="#step2-绑定组件">Step2. 绑定组件</a></li>
      </ul>
    </li>
    <li><a href="#二强制渲染组件">二、强制渲染组件</a></li>
    <li><a href="#三state-更新渲染组件">三、state 更新渲染组件</a>
      <ul>
        <li><a href="#1-单个-state-更新渲染">1. 单个 state 更新渲染</a></li>
        <li><a href="#2-多个-state-更新浅差异渲染">2. 多个 state 更新（浅差异）渲染</a></li>
        <li><a href="#3-自定义函数控制渲染">3. 自定义函数控制渲染</a></li>
      </ul>
    </li>
    <li><a href="#四记忆处理器避免重复计算">四、记忆处理器（避免重复计算）</a>
      <ul>
        <li><a href="#1-usecallback-处理器">1. useCallback() 处理器</a></li>
        <li><a href="#2-不依赖于作用域的处理器">2. 不依赖于作用域的处理器</a></li>
      </ul>
    </li>
    <li><a href="#五覆盖state抹去之前的state">五、覆盖state（抹去之前的state）</a></li>
    <li><a href="#六异步操作fetch请求">六、异步操作（fetch请求）</a></li>
    <li><a href="#七从-action-中读取-state">七、从 action 中读取 state</a></li>
    <li><a href="#八在-react-组件之外读写-state">八、在 React 组件之外读写 state</a>
      <ul>
        <li><a href="#1-自定义-hooks-读写-state">1. 自定义 hooks 读写 state</a></li>
        <li><a href="#2-使用订阅处理器中间件">2. 使用订阅处理器（中间件）</a></li>
        <li><a href="#3-订阅处理器中间件使用ts">3. 订阅处理器（中间件）使用TS</a></li>
      </ul>
    </li>
    <li><a href="#九瞬时更新ref用于频繁发生的状态变化">九、瞬时更新ref（用于频繁发生的状态变化）</a></li>
    <li><a href="#十更新嵌套的状态使用-immer">十、更新嵌套的状态，使用 Immer</a></li>
    <li><a href="#十一中间件">十一、中间件</a>
      <ul>
        <li><a href="#1-按自己喜欢的方式管理store">1. 按自己喜欢的方式管理store</a></li>
        <li><a href="#2-管理中间件">2. 管理中间件</a></li>
        <li><a href="#3-在管理中间件中使用ts">3. 在管理中间件中使用TS</a></li>
      </ul>
    </li>
    <li><a href="#十二状态持久化中间件-persist">十二、状态持久化中间件 persist</a>
      <ul>
        <li><a href="#1-快速示例">1. 快速示例</a></li>
        <li><a href="#2-选项">2. 选项</a></li>
        <li><a href="#3-api">3. API</a></li>
        <li><a href="#4-水合和异步存储">4. 水合和异步存储</a>
          <ul>
            <li><a href="#1-什么是水合hydration">1). 什么是水合hydration？</a></li>
            <li><a href="#2-如何检查-store-是否已水合">2). 如何检查 store 是否已水合</a></li>
          </ul>
        </li>
        <li><a href="#5-如何使用自定义存储引擎">5. 如何使用自定义存储引擎？</a></li>
      </ul>
    </li>
    <li><a href="#十三像-redux-一样编写代码">十三、像 Redux 一样编写代码</a></li>
    <li><a href="#十四在-react-事件处理程序之外调用-actions">十四、在 React 事件处理程序之外调用 actions</a></li>
    <li><a href="#十五使用-redux-开发工具">十五、使用 Redux 开发工具</a></li>
    <li><a href="#十六react-context">十六、React context</a>
      <ul>
        <li><a href="#1-创建-createcontext">1. 创建 createContext</a></li>
        <li><a href="#2-在组件中使用">2. 在组件中使用</a></li>
        <li><a href="#3-createcontext-使用-props-初始化在-ts-中">3. createContext 使用 props 初始化（在 TS 中）</a></li>
      </ul>
    </li>
    <li><a href="#十七typescript-类型定义">十七、TypeScript 类型定义</a>
      <ul>
        <li><a href="#1-类型定义">1. 类型定义</a></li>
        <li><a href="#2-使用combine-并让-tsc-推断类型">2. 使用<code>combine</code> 并让 tsc 推断类型</a></li>
      </ul>
    </li>
    <li><a href="#十八最佳实践将store拆分为单独的slice">十八、最佳实践（将store拆分为单独的slice）</a></li>
  </ul>
</nav>
  </div>
</div>
      
    </section>

  </div>
</div>

<script>
  'use strict';
  
  function wrap(el, wrapper) {
    el.parentNode.insertBefore(wrapper, el);
    wrapper.appendChild(el);
  }

  (function () {
    var singleContentsElem = document.querySelector('.single__contents');
    singleContentsElem ? 
    singleContentsElem.querySelectorAll('pre > code').forEach(function(elem) {
      var dataLang = elem.getAttribute('data-lang');
      var dataLangWrapper = document.createElement('div');
      var code = null;
      var codeTitle = null;

      if (dataLang && dataLang.includes(':')) {
        code = dataLang.split(':')[0];
        codeTitle = dataLang.split(':')[1];

        dataLangWrapper.className = 'language-' + code;
        dataLangWrapper.setAttribute('data-lang', codeTitle);

        elem.className = 'language-' + code;
        elem.setAttribute('data-lang', codeTitle);
        elem.setAttribute('id', codeTitle);
      }

      if (!dataLang || codeTitle) {
        wrap(elem.parentNode, dataLangWrapper);
      }

    }) : null;
  })();
  


  
  
  var dollarCodeElem = document.querySelectorAll('div.language-\\$');
  var gtCodeElem = document.querySelectorAll('div.language-\\>');
  
  dollarCodeElem ?
  dollarCodeElem.forEach(function(elem) {
    var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
    lnts ? 
    lnts.forEach(function(lnt) {
      lnt.innerHTML = '$<br/>';
    }) : null;
  }) : null;

  gtCodeElem ?
  gtCodeElem.forEach(function(elem) {
    var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
    lnts ? 
    lnts.forEach(function(lnt) {
      lnt.innerHTML = '><br/>';
    }) : null;
  }) : null;
  
</script>




<script defer src="/js/helper/getParents.min.js"></script>

<script defer src="/js/helper/closest.min.js"></script>

<script defer src="/js/helper/prev.min.js"></script>

<script defer src="/js/helper/prop.min.js"></script>

<script defer src="/js/helper/fadeinout.min.js"></script>












<script>
  document.addEventListener('DOMContentLoaded', function () {
    'use strict';
    
    
    var tables = document.querySelectorAll('.single__contents > table');
    for (let i = 0; i < tables.length; i++) {
      var table = tables[i];
      var wrapper = document.createElement('div');
      wrapper.className = 'table-wrapper';
      table.parentElement.replaceChild(wrapper, table);
      wrapper.appendChild(table);
    }
    


    
    
    
    var lib = JSON.parse("null");

    if (lib && lib.includes('mermaid')) {
      var themeVariant = localStorage.getItem('theme') || 'light';

      if (themeVariant === "dark") {
        mermaid.initialize({ theme: 'dark' });
      } else {
        mermaid.initialize({ theme: 'default' });
      }
      
      var mermaids = [];
      [].push.apply(mermaids, document.getElementsByClassName('language-mermaid'));
      mermaids.forEach(function(elem) {
        var elemParentNode = elem.parentNode;

        if (elemParentNode !== document.body) {
          elemParentNode.parentNode.insertBefore(elem, elemParentNode);
          elemParentNode.parentNode.removeChild(elemParentNode);
        }

        var newElemWrapper = document.createElement('div');
        newElemWrapper.classList.add('mermaid');
        newElemWrapper.innerHTML = elem.innerHTML;
        elem.replaceWith(newElemWrapper);
      });
    }
    
    

    
    if (lib && lib.includes('katex')) {
      var mathElements = document.getElementsByClassName('math');
      var options = {
        delimiters: [
          { left: "$$", right: "$$", display: true },
          { left: "\\[", right: "\\]", display: true },
          { left: "$", right: "$", display: false },
          { left: "\\(", right: "\\)", display: false }
        ],
      };

      renderMathInElement(document.querySelector('.single__contents'), options);
    }
    


    
    if (lib && lib.includes('flowchartjs')) {
      
      var options = JSON.parse("{\"arrow-end\":\"block\",\"element-color\":\"black\",\"fill\":\"white\",\"flowstate\":{\"approved\":{\"fill\":\"#58C4A3\",\"font-size\":12,\"no-text\":\"n/a\",\"yes-text\":\"APPROVED\"},\"current\":{\"fill\":\"yellow\",\"font-color\":\"red\",\"font-weight\":\"bold\"},\"future\":{\"fill\":\"#FFFF99\"},\"invalid\":{\"fill\":\"#444444\"},\"past\":{\"fill\":\"#CCCCCC\",\"font-size\":12},\"rejected\":{\"fill\":\"#C45879\",\"font-size\":12,\"no-text\":\"REJECTED\",\"yes-text\":\"n/a\"},\"request\":{\"fill\":\"blue\"}},\"font-color\":\"black\",\"font-size\":14,\"line-color\":\"black\",\"line-length\":50,\"line-width\":3,\"no-text\":\"no\",\"scale\":1,\"symbols\":{\"end\":{\"class\":\"end-element\"},\"start\":{\"element-color\":\"green\",\"fill\":\"yellow\",\"font-color\":\"red\"}},\"text-margin\":10,\"x\":0,\"y\":0,\"yes-text\":\"yes\"}");
      var jsonContent = null;

      var flowchartPrefix = "language-flowchart";
      var index = 0;
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + flowchartPrefix + "]"), function(x){
          x.style.display = 'none'
          x.parentNode.style.backgroundColor = "transparent"
          jsonContent = x.innerText;

          var node0 = document.createElement('div');
          node0.id = 'flowchart' + index;
          x.parentNode.insertBefore(node0, x);

          var diagram = flowchart.parse(jsonContent);
          diagram.drawSVG("flowchart"+index, options);

          index +=1;
      });      
    }
    


    
    if (lib && lib.includes('chart')) {
      var borderColor = "#666";
      var bgColor = "#ddd";
      var borderWidth = 2;

      Chart.defaults.global.elements.rectangle.borderWidth = borderWidth;
      Chart.defaults.global.elements.rectangle.borderColor = borderColor;
      Chart.defaults.global.elements.rectangle.backgroundColor = bgColor;

      Chart.defaults.global.elements.line.borderWidth = borderWidth;
      Chart.defaults.global.elements.line.borderColor = borderColor;
      Chart.defaults.global.elements.line.backgroundColor = bgColor;

      Chart.defaults.global.elements.point.borderWidth = borderWidth;
      Chart.defaults.global.elements.point.borderColor = borderColor;
      Chart.defaults.global.elements.point.backgroundColor = bgColor;

      var chartPrefix = "language-chart";
      var index = 0;
      var jsonContent = null;

      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + chartPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('canvas');
        var source = null;
        node0.height = 200;
        node0.style.height = 200;
        node0.id = 'myChart' + index;
        source = JSON.parse(jsonContent);
        x.parentNode.insertBefore(node0, x);
        var ctx = document.getElementById('myChart' + index).getContext('2d');
        var myChart = new Chart(ctx, source);
        index += 1;
      });            
    }
    


    
    if (lib && lib.includes('viz')) {
      var vizPrefix = "language-viz-";
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + vizPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        var engine;
        x.getAttribute("class").split(" ").forEach(function (cls) {
          if (cls.startsWith(vizPrefix)) {
            engine = cls.substr(vizPrefix.length);
          }
        });
        var viz = new Viz();
        viz.renderSVGElement(x.innerText, { engine: engine })
          .then(function (element) {
            element.style.width = "100%";
            x.parentNode.insertBefore(element, x);
          })
      });
    }
    
    
  });
</script>

<script>
  var listSide = document.getElementById('list-side');
  var listMain = document.getElementById('list-main');
  var singleMenu = document.getElementById('single-menu');
  var switchElem = document.querySelector('.switch');
  var wideViewAsDefault = JSON.parse("false");
  
  enquire.register("screen and (max-width:1280px)", {
    match: function () {
      if (wideViewAsDefault) {
        singleMenu.className = 'l';  
        listMain.className = 'mr';
        listSide.className = 'hide';
      } else {
        singleMenu.className = 'l';
        listMain.className = 'm';
        listSide.className = 'r';
      }
    },
    unmatch: function () {
      if (wideViewAsDefault) {
        singleMenu.className = 'l';
        listMain.className = 'mr';
        listSide.className = 'hide';
      } else {
        listSide.className = 'r';
        listMain.className = 'm';
        singleMenu.className = 'l';
      }
    },
  }).register("screen and (max-width:960px)", {
    match: function () {
      singleMenu.className = 'l';
      listMain.className = 'mr';
      listSide.className = 'hide';
      switchElem.className = 'hide';
    },
    unmatch: function () {
      if (wideViewAsDefault) {
        singleMenu.className = 'l';
        listMain.className = 'mr';
        listSide.className = 'hide';
      } else {
        singleMenu.className = 'l';
        listMain.className = 'm';
        listSide.className = 'r';
      }
      switchElem.className = 'switch';
    },
  }).register("screen and (max-width:600px)", {
    match: function () {
      listSide.className = 'hide';
      listMain.className = 'lmr';
      singleMenu.className = 'hide';
      switchElem.className = 'hide';
    },
    unmatch: function () {
      listSide.className = 'hide';
      listMain.className = 'mr';
      singleMenu.className = 'l';
      switchElem.className = 'hide';
    },
  });
</script>

        
<div class="bot">
  <footer class="footer">
    <div class="divider">
      <div class="lmr">
        
          <p class="caption">
            ©2022, codthing
          </p>
          
        
      </div>
    </div>
  </footer>
</div>

    </div>

</body>

</html>